将缩放图表的点映射到Windows窗体中的原始图表

时间:2018-01-12 15:58:28

标签: c# winforms

我有一个自定义的书面图表控件。我的图表在x轴上显示时间,在y轴上显示当前时间。我想要的是,选择缩放。因此,当用户单击并将鼠标拖到图表上时,它会显示选择矩形并选择图表上的特定区域并更新图表以显示仅选定区域的点。

我的问题是,我可以第一次放大,它会在更新的图表上显示正确的结果。使用正确更新的x坐标。但是当我再次这样做时(第一次放大后的任何时候)点总是关闭。

我想要的只是当用户在已经放大的图表中选择另一个区域时,它应该使用更新的x坐标进一步放大。

我尝试了什么:通过正确观察我的图表放大行为,我发现每次当我点击图表时,该点被映射到我的原始图表宽度而不是更新宽度(更新的宽度我发现为(endingXPoints - beginingXPoints)当我做缩放)。所以我必须根据更新的宽度来映射点。但这不起作用。我仍然没有得到正确的放大。我也尝试使用缩放因子,因为图表大小正在改变,但结果仍然不正确。

所以我的问题是如何在原始图表上绘制缩放图表的点。我是在Windows窗体中使用自定义编写的库。

我刚开始从事开发人员的职业生涯并仍处于学习过程中。任何建议对我都有很大的帮助。谢谢

这是我的mouse_up事件,如果该代码有帮助的话。我尝试添加尽可能多的注释。在这段代码中,我保存了点击堆栈的前一点,并使用它来获得比例因子并获得缩放

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 个答案:

答案 0 :(得分:0)

你必须映射积分吗?图表内置的缩放功能可以正确处理缩放,而无需重新发明轮子。下面的代码应该足够了,按住左键并拖动以放大范围。

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;
}

要缩小一个缩放,您需要在某处添加以下代码。在我下面的例子中,我右键单击鼠标。

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);
    }
}