I have a custom written chart control. My charts are displaying time on x-axis and current on y-axis. What I want is, selected zoom. So when user clicks and drag mouse over chart it shows selection rectangle and selects particular area on chart and updates the chart to display points of only selected area.
My problem is, I can zoom in for the first time and it shows me correct results on updated chart. with correctly updated x coordinates. But when I do it again (anytime after 1st zoom in) points are always off.
All I want is when user selects another area on already zoom in chart it should do further zoom in with updated x coordinates.
What I tried: From proper observation of my chart zoom in behavior I found that every time when I click on chart that point is mapped to my original chart width and not updated width(updated width I found as (endingXPoints - beginingXPoints) when I do zoom). So I have to map points according to updated width. But That does not work. I still do not get correct zoom in. Also I tried using scaling factor as chart size is changing but still result is not correct.
So my question how to map the points of zoomed chart on my original chart. I am doing this in windows form and using custom written library.
I just began my career as developer and still in learning process. Any suggestion will be great help to me. Thank you
Here is my mouse_up event, if that code helps. I have try to add as many comments as possible. In this code I am saving previous points clicked on stack and using it to get scale factor and get the scaled
private void chart_MouseUp(object sender, MouseEventArgs e)
{
Point p1, p2;
//when mouse up occurs it first checks, with isMousePressed, if mouse was pressed or not
if (isMousepressed)
{
isMousepressed = false;
isMouseEventOccured = true;
int xLeft = chartA.GetLeftDistToXaxis;//left distance from starting of control to x axis
int xWidth = chartA.chartWidth;//actual x-axis width shown on control
int yBottom = chartA.yTopPadding + chartA.chartHeight;//bottom distance from starting of control to y axis
//if no start - end points are selected then do nothing and return
if (endSelectionPoint == Point.Empty || beginSelectionPoint == Point.Empty) return;
//if start point is same as end point, do noting and return and if selection is made on left side of Y axis do nothing
if (endSelectionPoint.X == beginSelectionPoint.X) return;
if (endSelectionPoint.Y == beginSelectionPoint.Y) return;
if (beginSelectionPoint.X < xLeft && endSelectionPoint.X < xLeft) return;//avoid left chart area
if (beginSelectionPoint.Y > yBottom && endSelectionPoint.Y > yBottom) return;//avoid bottom chart area
endSelectionPoint.X = e.X;
endSelectionPoint.Y = e.Y;
//when all of the above conditions are false, we have two different start/end points which is not empty. map it & draw rectangle
p1 = ((Control)sender).PointToScreen(beginSelectionPoint);
p2 = ((Control)sender).PointToScreen(endSelectionPoint);
//draw selection rectangle
ControlPaint.DrawReversibleFrame(chartA.getRectangleForPoints(p1, p2), Color.Black, FrameStyle.Dashed);
//checking the begin and end value of x-y coordinates to see if they are on chart. if not then set the boundaries
//check it for begin coordinates
if (beginSelectionPoint.X < xLeft) { beginSelectionPoint.X = xLeft; }
if (beginSelectionPoint.X > (xLeft + chartA.Width)) { return; /*beginSelectionPoint.X = (xLeft + chartA.Width);*/ }
//if (beginSelectionPoint.Y < yBottom) { beginSelectionPoint.Y = yBottom; }
//if (beginSelectionPoint.Y > (yBottom + chartA.Height)) { beginSelectionPoint.Y = (yBottom + chartA.Height); }
//check it for end coordinates
if (endSelectionPoint.X > (xLeft + chartA.Width)) { endSelectionPoint.X = (xLeft + chartA.Width); }
if (endSelectionPoint.X < xLeft) { endSelectionPoint.X = xLeft; }
//if (endSelectionPoint.Y < yBottom) { endSelectionPoint.Y = yBottom; }
//if (endSelectionPoint.Y > (yBottom + chartA.Height)) { endSelectionPoint.Y = (yBottom + chartA.Height); }
//actual x-y value on chart.....x->corresponding time; y-> corresponding Amperage
xStart = 10 * chartA.MouseToXProportion(beginSelectionPoint.X );//multiplied with 10 to get the correct x values, if not used values in 0.+
yStart = chartA.MouseToYProportion(beginSelectionPoint.Y);
xEnd = 10 * chartA.MouseToXProportion(endSelectionPoint.X);
yEnd = chartA.MouseToYProportion(endSelectionPoint.Y);
if (zoomStack.Count != 0)
{
Point prevZoomPtEnd = (Point)zoomStack.Pop();
Point prevZoomPtStart = (Point)zoomStack.Pop();
double oldWidth = prevZoomPtEnd.X - prevZoomPtStart.X;
double zoomedWidth = endSelectionPoint.X - beginSelectionPoint.X;
double scaleFactor = zoomedWidth / oldWidth;
xStart = 10 * (chartA.MouseToXProportion(beginSelectionPoint.X) * scaleFactor);
xEnd = 10 * (chartA.MouseToXProportion(endSelectionPoint.X) * scaleFactor);
zoomStack.Push(beginSelectionPoint);
zoomStack.Push(endSelectionPoint);
}
else
{
zoomStack.Push(beginSelectionPoint);
zoomStack.Push(endSelectionPoint);
}
double xTemp;
if (xStart > xEnd) { xTemp = xEnd; xEnd = xStart; xStart = xTemp; }
//call updatechart() with start and end points on graph being p1/p2 or beginselection/endselection
updateChart(lastSelectedProfile, lastSelectedWeldIndex, xStart, xEnd);
}
else return;
}