Scaling Zoom factors - c#

I am using the scroll wheel to zoom in and out on an object using the following method:
void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
lastMousePositionOnTarget = Mouse.GetPosition(grid);
double max = 255;
double min = .005;
var deltaScale = Math.Max(Math.Log(scaleTransform.ScaleX), double.Epsilon);
var delta = e.Delta > 0 ? Math.Max(e.Delta * deltaScale, .5) : Math.Min(e.Delta * deltaScale, -.5);
double newScale = Math.Max(Math.Min((delta / 250d) + scaleTransform.ScaleX, max), min);
scaleTransform.ScaleX = newScale;
scaleTransform.ScaleY = newScale;
System.Diagnostics.Debug.WriteLine(newScale);
e.Handled = true;
}
I want to have it zoom more slowly when it is zoomed in closer to the max, and faster when the number is closer to the minimum. What I currently have sort of works but not very well. How can I fix this to do what I want?

Assuming I understand this right, you want your deltaScale to be large when zoomed in, but small when zoomed out. Thereby giving you fast zooming when close and slow zooming when far.
If scaletransform.ScaleX gets smaller as you're zoomed in, try something like this:
var deltaScale = Math.Max(K * 1/(scaleTransform.ScaleX), double.Epsilon);
where K is just some const you mess around with until it feels right.
If scaletransform.ScaleX gets larger as you're zoomed in, then try something like like your log, with a larger coefficient than 1:
var deltaScale = Math.Max(5*Math.Log(scaleTransform.ScaleX), double.Epsilon);

This is my final answer, I wouldn't have been able to come up with it if not for GEEF & Pawel so a big thanks to them for giving it their best shot.
void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
double max = 255;
double min = .005;
double scaler = 4;
var deltaScale = Math.Min(Math.Max(scaler * scaleTransform.ScaleX / max, min),1) * Math.Sign(e.Delta);
double newScale = Math.Max(Math.Min(deltaScale + scaleTransform.ScaleX, max), min);
scaleTransform.ScaleX = newScale;
scaleTransform.ScaleY = newScale;
e.Handled = true;
}
I use a ratio of the current scale to the max to get the slope -- and don't allow it to go to fast (max 1) or too slow, min == the min scale. Works OK.

First of all I would not use value e.Delta for calculations (sign is of course needed). This value is not very reliable - in my experience it was close to random noise. Instead use constant value or some counter like how many times in a row zoom in was invoked and how many times in a row zoom out was invoked.
So my first try (with constant value) would look somehow like this.
void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
lastMousePositionOnTarget = Mouse.GetPosition(grid);
double max = 255;
double min = .005;
var deltaScale = Math.Max(Math.Log(scaleTransform.ScaleX), double.Epsilon);
var delta = e.Delta > 0 ? Math.Max(1 * deltaScale, .5) : Math.Min(1 * deltaScale, -.5);
double newScale = Math.Max(Math.Min((delta / 250d) + scaleTransform.ScaleX, max), min);
scaleTransform.ScaleX = newScale;
scaleTransform.ScaleY = newScale;
System.Diagnostics.Debug.WriteLine(newScale);
e.Handled = true;
}
Version with counters would look something like this.
private double counter=0;
private bool isZoomIn=true;
void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
lastMousePositionOnTarget = Mouse.GetPosition(grid);
if( (e.Delta > 0 && isZoomIn) || (e.Delta < 0 && !isZoomIn))
IncreaseCounter(counter);//is another one in a row
else
counter=1;
isZoomIn = e.Delta > 0;//we set this flag for next time
double max = 255;
double min = .005;
var deltaScale = Math.Max(Math.Log(scaleTransform.ScaleX), double.Epsilon);
var delta = e.Delta > 0 ? Math.Max(counter * deltaScale, .5) : Math.Min(counter * deltaScale, -.5);
double newScale = Math.Max(Math.Min((delta / 250d) + scaleTransform.ScaleX, max), min);
scaleTransform.ScaleX = newScale;
scaleTransform.ScaleY = newScale;
System.Diagnostics.Debug.WriteLine(newScale);
e.Handled = true;
}
Note that I used pseudofunction IncreaceCounter instead of just incrementaion because you may want something else than just linear increase.

Related

c# Chart y-axis scaling uniformly

I'm using a device that receives a pressure reading in a 4-20MA, converts it to a voltage and scales that within a range and then charts the data in a line graph, live. I am scaling the y-axis and have buttons in place to adjust the y-axis scale during runtime depending on how big the range is needed. So in otherwords, if the pressure starts at 0 psi, then jumps all the way to 20,000, I want the chart to show -100 (minimum - only so that if PSI is at 0, its visible) to 0, 100, 200, ..., 19800, 19900, 20000. But instead if pressure is at say 19743, the scale is "-43, 43, 143, ..., 19843, 19943" something like that. Is there a way to change this so it only counts by "whole hundreds" or something?
My y-axis interval is jumping by 50's so the axis can go 0, 50, 100,... or 0, 100, 200, etc. and so on (Able to jump 500 psi at a time if desired). But I just want to y-axis numbers to show whole hundreds, if that makes sense.
My maximum y-value is the max incoming value (I'm comparing 3 input values) and adding 1,000 to that. So if the current max pressure is 19,000 psi, the chart should show -100 to 20,0000.
My comparisons of incoming values - The names are "RawIn#" but these are already scaled. Bad variable naming, I know.
if (rawIn0 > rawIn1)
{
maxY = Convert.ToInt32(rawIn0);
}
else if (rawIn1 > rawIn0)
{
maxY = Convert.ToInt32(rawIn1);
}
if (maxY < rawIn2)
{
maxY = Convert.ToInt32(rawIn2);
}
if (maxY > absoluteMaxY)
{
absoluteMaxY = maxY;
}
if (rawIn0 > rawIn1)
{
minY = Convert.ToInt32(rawIn1);
}
else if (rawIn1 > rawIn0)
{
minY = Convert.ToInt32(rawIn0);
}
if (minY > rawIn2)
{
minY = Convert.ToInt32(rawIn2);
}
The current way I'm scaling the chart. MinY is always 0. So minimum = -100.
chart1.ChartAreas[0].AxisY.Maximum = absoluteMaxY + 1000;
chart1.ChartAreas[0].AxisY.Minimum = minY - 100;
My buttons on runtime to increase and decrease the interval. The higher the // interval, the easier it is to see the entire chart with less y-axis lines.
private void yValueSizeInc_Click(object sender, EventArgs e)
{
if (chart1.ChartAreas[0].AxisY.Interval < 50)
{
chart1.ChartAreas[0].AxisY.Interval = 50;
}
else
{
chart1.ChartAreas[0].AxisY.Interval += 50;
}
Properties.Settings.Default.pressureInterval =
(int)chart1.ChartAreas[0].AxisY.Interval;
yValueSize.Text = chart1.ChartAreas[0].AxisY.Interval.ToString();
}
private void yValueSizeDec_Click(object sender, EventArgs e)
{
if (chart1.ChartAreas[0].AxisY.Interval <= 50)
{
chart1.ChartAreas[0].AxisY.Interval = 50;
}
else
{
chart1.ChartAreas[0].AxisY.Interval -= 50;
}
Properties.Settings.Default.pressureInterval = (int)
chart1.ChartAreas[0].AxisY.Interval;
yValueSize.Text = chart1.ChartAreas[0].AxisY.Interval.ToString();
}
Pressure count can be seen not uniform

Alternatives to the HitTest()

Currently my software uses the HitTest() method of a chart object in MSCharts but as I scale this up to more and more data points on my chart combined with other factors this can have a massive performance hit.
I was wondering if there any alternatives that you know of to provide the same functionality ( get the X Coordinate on the chart for the cursor position ) but without the performance hit as hit testing seems to be a very brute force way of obtaining my answer.
My chart is created from the class System.Windows.Forms.DataVisualization.Charting.Chart
Edit for clarity: I need to find the position of a line on my chart to use it for other calculations.
Had the same performance issue with a mousewheel event.
Here is my solution:
To get the axes values of the current mouse position:
double posX = Math.Round(currentArea.AxisX.PixelPositionToValue(e.X));
double posY = Math.Round(currentArea.AxisY.PixelPositionToValue(e.Y));
Taken from Showing Mouse Axis Coordinates on Chart Control with a little change to get it more accurate.
But you should check before, that the mouse is in a ChartArea, else it will throw you an Exception.
To get the ChatElement on which the mouse points:
// Gets the ChartArea that the mouse points
private ChartArea mouseinChartArea(Chart source, Point e)
{
double relativeX = (double)e.X * 100 / source.Width;
double relativeY = (double)e.Y * 100 / source.Height;
foreach (ChartArea ca in source.ChartAreas)
{
if (relativeX > ca.Position.X && relativeX < ca.Position.Right &&
relativeY > ca.Position.Y && relativeY < ca.Position.Bottom)
return ca;
}
return null;
}
// for my purpose, returns an axis. But you can return anything
private Axis findAxisforZooming(Chart source, Point e)
{
ChartArea currentArea = mouseinChartArea(source, new Point(e.X, e.Y)); // Check if inside
if (currentArea == null)
return null;
double axisXfontSize = currentArea.AxisX.LabelAutoFitMinFontSize + ((double)source.Width / SystemInformation.PrimaryMonitorSize.Width)
* (currentArea.AxisX.LabelAutoFitMaxFontSize - currentArea.AxisX.LabelAutoFitMinFontSize);
double axisYfontSize = currentArea.AxisY.LabelAutoFitMinFontSize + ((double)source.Height / SystemInformation.PrimaryMonitorSize.Height)
* (currentArea.AxisY.LabelAutoFitMaxFontSize - currentArea.AxisY.LabelAutoFitMinFontSize);
double axisYfontHeightSize = (axisYfontSize - currentArea.AxisY.LabelStyle.Font.Size) + currentArea.AxisY.LabelStyle.Font.Height;
Graphics g = this.CreateGraphics();
if (currentArea.AxisX.LabelStyle.Font.Unit == GraphicsUnit.Point)
axisXfontSize = axisXfontSize * g.DpiX / 72;
if (currentArea.AxisY.LabelStyle.Font.Unit == GraphicsUnit.Point)
axisYfontHeightSize = axisYfontHeightSize * g.DpiX / 72;
g.Dispose();
// Replacing the SystemInformation.PrimaryMonitorSize with the source.Width / Height will give the accurate TickMarks size.
// But it doens't count for the gab between the tickMarks and the axis lables (so by replacing, it give a good proximity with the gab)
int axisYTickMarks = (int)Math.Round(currentArea.AxisY.MajorTickMark.Size / 100 * SystemInformation.PrimaryMonitorSize.Width); // source.Width;
int axisXTickMarks = (int)Math.Round(currentArea.AxisX.MajorTickMark.Size / 100 * SystemInformation.PrimaryMonitorSize.Height); // source.Height;
int leftInnerPlot = (int)Math.Round(currentArea.Position.X / 100 * source.Width +
currentArea.InnerPlotPosition.X / 100 * currentArea.Position.Width / 100 * source.Width);
int rightInnerPlot = (int)Math.Round(currentArea.Position.X / 100 * this.chart1.Width +
currentArea.InnerPlotPosition.Right / 100 * currentArea.Position.Width / 100 * source.Width);
int topInnerPlot = (int)Math.Round(currentArea.Position.Y / 100 * this.chart1.Height +
currentArea.InnerPlotPosition.Y / 100 * currentArea.Position.Height / 100 * source.Height);
int bottomInnerPlot = (int)Math.Round(currentArea.Position.Y / 100 * source.Height +
currentArea.InnerPlotPosition.Bottom / 100 * currentArea.Position.Height / 100 * source.Height);
// Now you got the boundaries of every important ChartElement.
// Only left to check if the mouse is within your desire ChartElement,
// like the following:
bottomInnerPlot += axisXTickMarks + (int)Math.Round(axisXfontSize); // Include AxisX
if (e.X > leftInnerPlot && e.X < rightInnerPlot &&
e.Y > topInnerPlot && e.Y < bottomInnerPlot) // return AxisX if inside the InnerPlot area or on AxisX
return currentArea.AxisX;
else if (e.X > (leftInnerPlot - axisYTickMarks - (int)Math.Round(axisYfontHeightSize)) && e.X < rightInnerPlot &&
e.Y > topInnerPlot && e.Y < bottomInnerPlot) // return AxisY if on AxisY only
return currentArea.AxisY;
return null;
}
As it can be seen, the code is longer than HitTest(). But the run time is shorter.

System.IndexOutOfRangeException when calling GetPixel() on a WriteableBitmap

private void selectColor_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
xMove += e.DeltaManipulation.Translation.X;
yMove += e.DeltaManipulation.Translation.Y;
double xMax = 350;
double yMax = 40;
if (xMove < 0)
{
xMove = 0;
}
else if (xMove > xMax)
{
xMove = xMax;
}
if (yMove < 0)
{
yMove = 0;
}
else if (yMove > yMax)
{
yMove = yMax;
}
int x = Convert.ToInt32(xMove);
int y = Convert.ToInt32(yMove);
var writeableBmp = new WriteableBitmap(selectColor, null);
var tempColor = writeableBmp.GetPixel(x, y);
Brush imageColor = new SolidColorBrush(tempColor);
txtBlockName.Foreground = imageColor;
}
This function is for handling the manipulationDelta when i tap and drag inside the canvas called selectColor. yMove and xMove are 2 doubles that record the total movement. they are declared prio to the function. As the title states i get a IndexOutOfRangeException, and it points at x. I dont see how that is possible since i have set max/min values that are within the canvas. My canvas is exactly 350x40, so when x = 180 it shouldn't give me this error. I am a little confused right now, any help/advice will be appreciated.
Set the limits to
double xMax = 349;
double yMax = 39;
0 .. 349 = 350 pixels
0 .. 39 = 40 pixels
You are off-by-one when you set the xMove and yMove to the actual max values

Make an Image Scale with Mouse Scroll Wheel XNA

I have an image that I want to increase the size or decrease the size if the mouse wheel is scrolled up or down accordingly. If the image reaches a set max size it will not get ant larger and vice versa if making the image smaller. The problem I am having is once you reach the maximum size of the image and continue scrolling up then go to scroll down the image will not get smaller right away until you scrolled down the same number of times you scrolled up while having the image at the max size and again reverse for making the image smaller. ScrollWheelValue is an read only property so it cannot be reset. I was trying to add some logic where if the wheel is scrolled up and the image is max size subtract 120 because 120 is what the mouse increases per scroll. Can anyone help me with this issue? Thanks very much
Original Code:
float scale = ms.ScrollWheelValue / 120;
scaleFactor = scale * scaleChange;
if (scaleFactor > MAX_SCALE)
{
scaleFactor = MAX_SCALE;
}
else if (scaleFactor < MIN_SCALE)
{
scaleFactor = MIN_SCALE;
}
New Code:
if (scaleFactor > MAX_SCALE)
{
scaleFactor = MAX_SCALE;
float newScale = ms.ScrollWheelValue / 120;
if (newScale > scale)
{
scaleCount = scaleCount - 120;
}
if (newScale < scale)
{
scaleCount = scaleCount + 120;
}
}
else if (scaleFactor < MIN_SCALE)
{
scaleFactor = MIN_SCALE;
float newScale = ms.ScrollWheelValue / 120;
if (newScale > scale)
{
scaleCount = scaleCount - 120;
}
if (newScale < scale)
{
scaleCount = scaleCount + 120;
}
}
else
{
scale = ms.ScrollWheelValue / 120 + scaleCount;
scaleFactor = scale * scaleChange;
}
If you read:
MSDN MouseState Scroll Wheel Value
You'll see that it keeps a running value from the beginning of the game. So what you want to do is check it for a change vs. the previous value and do something accordingly.
How you have it set up it seems you don't care about the actual value, just the difference since the last time they scrolled the wheel.
declare these outside of your update loop:
float prevWheelValue;
float currWheelValue;
Then in your update:
prevWheelValue = currWheelValue;
currWheelValue = ms.ScrollWheelValue;
now your checks can simply be if prevWheelValue > < or == to currWheelValue and clamp the value to the boundaries that you want.
Mathhelper.Clamp

Showing Mouse Axis Coordinates on Chart Control

Is there a simple way to retrieve the X/Y coordinates of ANY point in the chart Area (relative to that chart Axis of course)?
As of now, I just managed to retrieve coordinates when the mouse is on a Series (not outside)
private void chart_GetToolTipText(object sender, ToolTipEventArgs e)
{
if (e.HitTestResult.Series != null)
{
e.Text = e.HitTestResult.Series.Points[e.HitTestResult.PointIndex].YValues[0] + " \n " + DateTime.FromOADate(e.HitTestResult.Series.Points[e.HitTestResult.PointIndex].XValue);
}
}
Anyway, as always with MS Chart Controls, there is no easy way to do things, but a funky workaround to get things done. I am sadly getting used to it...
private void chart1_MouseWhatever(object sender, MouseEventArgs e)
{
chartArea1.CursorX.SetCursorPixelPosition(new Point(e.X, e.Y), true);
chartArea1.CursorY.SetCursorPixelPosition(new Point(e.X, e.Y), true);
double pX = chartArea1.CursorX.Position; //X Axis Coordinate of your mouse cursor
double pY = chartArea1.CursorY.Position; //Y Axis Coordinate of your mouse cursor
}
This works for my purposes and doesn't side effect the cursor.
private Tuple<double,double> GetAxisValuesFromMouse(int x, int y)
{
var chartArea = _chart.ChartAreas[0];
var xValue = chartArea.AxisX.PixelPositionToValue(x);
var yValue = chartArea.AxisY.PixelPositionToValue(y);
return new Tuple<double, double>(xValue, yValue);
}
I tried your answer, but it didn't work for me. It ended up putting the cursor in one spot and never moving. I believe this is because I use decimal/double values along both axes, and the cursor is being rounded to the nearest integer.
After several attempts, I was able to work out a method for determining where the cursor is inside the chart. The hard part was figuring out that all the "positions" for the chart elements are actually percentage values (from 0 to 100).
As per
http://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.elementposition.aspx:
"Defines the position of the chart element in relative coordinates, which range from (0,0) to (100,100)."
I hope you don't mind, I am posting this answer here just for posterity, in case anyone else comes across this problem, and your method also does not work for them. Its not pretty or elegant in any way, but so far it works for me.
private struct PointD
{
public double X;
public double Y;
public PointD(double X, double Y)
{
this.X = X;
this.Y = Y;
}
}
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
var pos = LocationInChart(e.X, e.Y);
lblCoords.Text = string.Format("({0}, {1}) ... ({2}, {3})", e.X, e.Y, pos.X, pos.Y);
}
private PointD LocationInChart(double xMouse, double yMouse)
{
var ca = chart1.ChartAreas[0];
//Position inside the control, from 0 to 100
var relPosInControl = new PointD
(
((double)xMouse / (double)execDetailsChart.Width) * 100,
((double)yMouse / (double)execDetailsChart.Height) * 100
);
//Verify we are inside the Chart Area
if (relPosInControl.X < ca.Position.X || relPosInControl.X > ca.Position.Right
|| relPosInControl.Y < ca.Position.Y || relPosInControl.Y > ca.Position.Bottom) return new PointD(double.NaN, double.NaN);
//Position inside the Chart Area, from 0 to 100
var relPosInChartArea = new PointD
(
((relPosInControl.X - ca.Position.X) / ca.Position.Width) * 100,
((relPosInControl.Y - ca.Position.Y) / ca.Position.Height) * 100
);
//Verify we are inside the Plot Area
if (relPosInChartArea.X < ca.InnerPlotPosition.X || relPosInChartArea.X > ca.InnerPlotPosition.Right
|| relPosInChartArea.Y < ca.InnerPlotPosition.Y || relPosInChartArea.Y > ca.InnerPlotPosition.Bottom) return new PointD(double.NaN, double.NaN);
//Position inside the Plot Area, 0 to 1
var relPosInPlotArea = new PointD
(
((relPosInChartArea.X - ca.InnerPlotPosition.X) / ca.InnerPlotPosition.Width),
((relPosInChartArea.Y - ca.InnerPlotPosition.Y) / ca.InnerPlotPosition.Height)
);
var X = relPosInPlotArea.X * (ca.AxisX.Maximum - ca.AxisX.Minimum) + ca.AxisX.Minimum;
var Y = (1 - relPosInPlotArea.Y) * (ca.AxisY.Maximum - ca.AxisY.Minimum) + ca.AxisY.Minimum;
return new PointD(X, Y);
}
private void OnChartMouseMove(object sender, MouseEventArgs e)
{
var sourceChart = sender as Chart;
HitTestResult result = sourceChart.HitTest(e.X, e.Y);
ChartArea chartAreas = sourceChart.ChartAreas[0];
if (result.ChartElementType == ChartElementType.DataPoint)
{
chartAreas.CursorX.Position = chartAreas.AxisX.PixelPositionToValue(e.X);
chartAreas.CursorY.Position = chartAreas.AxisY.PixelPositionToValue(e.Y);
}
}
This works
private void chart1_MouseWhatever(object sender, MouseEventArgs e)
{
Point chartLocationOnForm = chart1.FindForm().PointToClient(chart1.Parent.PointToScreen(chart1.Location));
double x = chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X - chartLocationOnForm.X);
double y = chart1.ChartAreas[0].AxisY.PixelPositionToValue(e.Y - chartLocationOnForm.Y);
}
And this works
private void chart1_MouseWhatever(object sender, MouseEventArgs e)
{
Point chartLocationOnForm = chart1.FindForm().PointToClient(chart1.Parent.PointToScreen(chart1.Location));
chart1.ChartAreas[0].CursorX.SetCursorPixelPosition(new PointF(e.X - chartLocationOnForm.X, e.Y - chartLocationOnForm.Y), true);
chart1.ChartAreas[0].CursorY.SetCursorPixelPosition(new PointF(e.X - chartLocationOnForm.X, e.Y - chartLocationOnForm.Y), true);
double x = chart1.ChartAreas[0].CursorX.Position;
double y = chart1.ChartAreas[0].CursorY.Position;
}
This is what I got, I think many of us are along the same lines but with different interpretations of what it is you're looking for.
This will give you the coordinates at any location in the plotting area. I found the HitTest gives a clean and simple solution, but there are a few checks to make, whether the cursor is on a data point, a gridline, or in the plotting area (which seem to take precedence in that order). I assume you'll be interested in the coordinate regardless of which of those objects the mouse is over.
private void chart_GetToolTipText(object sender, ToolTipEventArgs e)
{
// If the mouse isn't on the plotting area, a datapoint, or gridline then exit
HitTestResult htr = chart.HitTest(e.X, e.Y);
if (htr.ChartElementType != ChartElementType.PlottingArea && htr.ChartElementType != ChartElementType.DataPoint && htr.ChartElementType != ChartElementType.Gridlines)
return;
ChartArea ca = chart.ChartAreas[0]; // Assuming you only have 1 chart area on the chart
double xCoord = ca.AxisX.PixelPositionToValue(e.X);
double yCoord = ca.AxisY.PixelPositionToValue(e.Y);
e.Text = "X = " + Math.Round(xCoord, 2).ToString() + "\nY = " + Math.Round(yCoord, 2).ToString();
}
VB.net version, with zoom correction:
Private Function LocationInChart(xMouse, yMouse) As PointF
Dim ca = Chart1.ChartAreas(0)
'Position inside the control, from 0 to 100
Dim relPosInControl = New PointF((xMouse / Chart1.Width) * 100, (yMouse / Chart1.Height) * 100)
'Verify we are inside the Chart Area
If (relPosInControl.X < ca.Position.X Or relPosInControl.X > ca.Position.Right Or relPosInControl.Y < ca.Position.Y Or relPosInControl.Y > ca.Position.Bottom) Then Return New PointF(Double.NaN, Double.NaN)
'Position inside the Chart Area, from 0 to 100
Dim relPosInChartArea = New PointF(((relPosInControl.X - ca.Position.X) / ca.Position.Width) * 100, ((relPosInControl.Y - ca.Position.Y) / ca.Position.Height) * 100)
'Verify we are inside the Plot Area
If (relPosInChartArea.X < ca.InnerPlotPosition.X Or relPosInChartArea.X > ca.InnerPlotPosition.Right Or relPosInChartArea.Y < ca.InnerPlotPosition.Y Or relPosInChartArea.Y > ca.InnerPlotPosition.Bottom) Then Return New PointF(Double.NaN, Double.NaN)
'Position inside the Plot Area, 0 to 1
Dim relPosInPlotArea = New PointF(((relPosInChartArea.X - ca.InnerPlotPosition.X) / ca.InnerPlotPosition.Width), ((relPosInChartArea.Y - ca.InnerPlotPosition.Y) / ca.InnerPlotPosition.Height))
Dim X = relPosInPlotArea.X * (ca.AxisX.Maximum - ca.AxisX.Minimum) + ca.AxisX.Minimum
Dim Y = (1 - relPosInPlotArea.Y) * (ca.AxisY.Maximum - ca.AxisY.Minimum) + ca.AxisY.Minimum
' zoomo korekcija
Dim zoomx = (ca.AxisX.ScaleView.ViewMaximum - ca.AxisX.ScaleView.ViewMinimum) / (ca.AxisX.Maximum - ca.AxisX.Minimum)
Dim zoomy = (ca.AxisY.ScaleView.ViewMaximum - ca.AxisY.ScaleView.ViewMinimum) / (ca.AxisY.Maximum - ca.AxisY.Minimum)
Dim xx = ca.AxisX.ScaleView.ViewMinimum + X * zoomx
Dim yy = ca.AxisY.ScaleView.ViewMinimum + Y * zoomy
Return New PointF(xx, yy)
End Function

Categories