0
votes

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;   
}
1
I have a custom written chart control What does that mean? A MSChart subclass?TaW
MS Chart uses DataVisualization, if I am not wrong. Code that i am working on does not use that package. They created chart using rectangle class, added lines as X-Y axis, providing x-y axis labels and top/bottom padding.user2923684
Aha. So, how could we help without knowing anything about your code??TaW
I can post the code for mouse move up event, if that helps and try to explain as much as possible some fields used in ituser2923684

1 Answers

0
votes

Do you have to map the points? The chart's built in zoom should handle zooming correctly without trying to re-invent the wheel. The code below should be enough, hold left click and drag to zoom into the range.

private void setUserSelection(Chart cht)
{
    cht.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
    cht.ChartAreas[0].CursorX.IsUserEnabled = true;
    cht.ChartAreas[0].CursorX.LineColor = Color.Transparent;
    cht.ChartAreas[0].CursorX.SelectionColor = Color.Lime;
    cht.ChartAreas[0].CursorX.Interval = 0;
    cht.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
    cht.ChartAreas[0].AxisX2.ScaleView.Zoomable = true;

    cht.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
    cht.ChartAreas[0].CursorY.IsUserEnabled = true;
    cht.ChartAreas[0].CursorY.LineColor = Color.Transparent;
    cht.ChartAreas[0].CursorY.SelectionColor = Color.Lime;
    cht.ChartAreas[0].CursorY.Interval = 0;
    cht.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
    cht.ChartAreas[0].AxisY2.ScaleView.Zoomable = true;
}

To zoom out back one zoom, you'll need to add the following code somewhere. In my example below I have mine on the mouse right click.

private void chart1_MouseClick(object sender, MouseEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Right)
    {
        chart1.ChartAreas[0].AxisX.ScaleView.ZoomReset(1);
        chart1.ChartAreas[0].AxisY.ScaleView.ZoomReset(1);
    }
}