如何将图像设置为沿图表轴或沿图表轴放置? [英] How does one set an image as or along a chart axis?

查看:104
本文介绍了如何将图像设置为沿图表轴或沿图表轴放置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用彩色光谱带作为图表的轴.想法是使图像上的颜色与其相关的沿底部x轴的波长相匹配.条形图需要更改大小以匹配图表区域的变化,并需要扩展和收缩部分以匹配图表区域中的滚动缩放.

I am trying to use a colored spectrum strip as an axis for a chart. The idea is to match the color on the image with its associated wavelength along the x-axis at the bottom. The strip needs to change in size to match changes of the chart area and expand and contract sections to match scroll-zooming in the chart area.

我尝试使用图像注释,但是随着图表区域的更改,注释尺寸保持固定.另外,聚焦于鼠标位置的滚动缩放显然不会对注释产生影响.

I have tried using image annotations but as the chart area changes, the annotation dimensions remain fixed. Also, the scroll zooming that focuses in on mouse position obviously has no effect on the annotation.

最接近的方法是将图像用作图表区域的背景.随着图表区域的更改,图像会自动缩放,但滚动缩放不会对背景图像产生影响.同样,理想的是使背景清晰,以避免模糊数据绘图点.我可以将图像编辑为具有较大的透明部分,并在底部仅有一个彩色条,但是即使那样,该条也可以遮盖较低强度的数据点.

The approach that came closest was using the image as a background for the chart area. This automatically scaled the image as the chart area changed but scroll-zooming has no effect on the background image. Also, it would be ideal to have the background clear so as to avoid obscuring data plot points. I can edit the image to have a large transparent section and only a colored strip at the bottom but even then, that strip could obscure lower intensity data points.

光谱作为注释和背景:

Spectrum as annotation and background:

注释未缩放,背景缩放良好:

Annotation not scaling, background scales well:

注释和背景都无法通过缩放来缩放:

Both annotation and background not scaling with zooming:

推荐答案

这是一个好主意.

最简单的方法是在图表的Paint事件(可能是PrePaint)中绘制图像.

The simplest way is to draw the image in a Paint event of the Chart, maybe PrePaint.

开始工作..我们将使用

Let's go to work.. We will use the DrawImage overload that allows us zooming as well as cropping. For this we need two rectangles.

第一个挑战是始终获得正确的目标矩形.

The first challenge is to always get the correct target rectangle.

为此,我们需要将InnerPlotPosition从相对位置转换为绝对像素.

For this we need to convert the InnerPlotPosition from relative positions to absolute pixels.

这两个功能会有所帮助:

These two functions will help:

RectangleF ChartAreaClientRectangle(Chart chart, ChartArea CA)
{
    RectangleF CAR = CA.Position.ToRectangleF();
    float pw = chart.ClientSize.Width / 100f;
    float ph = chart.ClientSize.Height / 100f;
    return new RectangleF(pw * CAR.X, ph * CAR.Y, pw * CAR.Width, ph * CAR.Height);
}

RectangleF InnerPlotPositionClientRectangle(Chart chart, ChartArea CA)
{
    RectangleF IPP = CA.InnerPlotPosition.ToRectangleF();
    RectangleF CArp = ChartAreaClientRectangle(chart, CA);

    float pw = CArp.Width / 100f;
    float ph = CArp.Height / 100f;

    return new RectangleF(CArp.X + pw * IPP.X, CArp.Y + ph * IPP.Y, 
                            pw * IPP.Width, ph * IPP.Height);
}

使用这些数字设置目标矩形非常简单:

With these numbers setting the destination rectangle is as simple as:

Rectangle tgtR = Rectangle.Round(new RectangleF(ipr.Left, ipr.Bottom - 15, ipr.Width, 15));

您可以根据需要选择一个高度.

You can chose a height as you like..

下一个挑战是源矩形.

不缩放就简单地是:

Rectangle srcR = new Rectangle( 0, 0, bmp.Width, bmp.Height);

但是对于缩放和平移,我们需要对其进行缩放;为此,我们可以使用x轴和ScaleViewMinimumMaximum值.

But for zooming and panning we need to scale it; for this we can use the x-axis and the ScaleView's Minimum and Maximum values.

我们计算轴上第一个点和最后一个点的因子:

We calculate factors for the first and last spot on the axis:

double f1 = ax.ScaleView.ViewMinimum / (ax.Maximum - ax.Minimum);
double f2 = ax.ScaleView.ViewMaximum / (ax.Maximum - ax.Minimum);

现在我们得到的源矩形可能是这样的:

now we get the source rectangle maybe like this:

int x  = (int)(bmp.Width * f1);
int xx = (int)(bmp.Width * f2);
Rectangle srcR = new Rectangle( x, 0, xx - x, bmp.Height);

让我们放在一起:

private void chart_PrePaint(object sender, ChartPaintEventArgs e)
{
    // a few short names
    Graphics g = e.ChartGraphics.Graphics;  
    ChartArea ca = chart.ChartAreas[0];
    Axis ax = ca.AxisX;

    // pixels of plot area
    RectangleF ipr = InnerPlotPositionClientRectangle(chart, ca);

    // scaled first and last position
    double f1 = ax.ScaleView.ViewMinimum / (ax.Maximum - ax.Minimum);
    double f2 = ax.ScaleView.ViewMaximum / (ax.Maximum - ax.Minimum);

    // actual drawing with the zooming overload
    using (Bitmap bmp = (Bitmap)Bitmap.FromFile(imagePath))
    {
        int x  = (int)(bmp.Width * f1);
        int xx = (int)(bmp.Width * f2);
        Rectangle srcR = new Rectangle( x, 0, xx - x, bmp.Height);
        Rectangle tgtR = Rectangle.Round(
                         new RectangleF(ipr.Left , ipr.Bottom - 15, ipr.Width, 15));
        g.DrawImage(bmp, tgtR, srcR, GraphicsUnit.Pixel);
    }
}

一些注意事项:

  • 我当然建议使用Image资源,而不是总是从磁盘加载!

  • Of course I would recomend to use an Image resource instead of always loading from disk!

图形将始终覆盖数据点以及网格.你也可以.

The Drawing will always overlay the data points and also the grids. You can either..

  • 选择不同的最小值腾出空间
  • 缩小图像
  • 将其移动到x轴标签下方
  • 使图像半透明
  • 将x轴设置得很胖,以使其可以容纳图像带:ax.LineWidth = 10
  • choose a different minimum to make room
  • make the image smaller
  • move it below the x-axis labels
  • make the image semi-transparent
  • make the x-axis so fat that it can hold the image strip : ax.LineWidth = 10

对于后一种解决方案,您可能希望根据缩放状态偏移y位置.又快又脏:int yoff = (ax.ScaleView.IsZoomed ? 12 : 5);.为了避免出现黑色条纹,还应将轴设置为透明"或"chart.BackColor ..

For the latter solution you would want to offset the y-position depending on the zoom state. Quick and dirty: int yoff = (ax.ScaleView.IsZoomed ? 12 : 5);. To avoid black stripes also make the axis Transparent or chart.BackColor..

更新:

您还可以还原为使用StripLine.它可以缩放其BackgroundImage,并且每当更改比例视图时(即缩放或平移时),您都必须创建合适的图像.为此,上面的许多代码将用于创建新图像.请参阅这篇文章,以了解如何在图表中添加和替换不同的NamedImage ! (有关标记图像的相关部分接近结尾!)

You can also revert to using a StripLine. It can scale its BackgroundImage and you would have to create a suitable image whenever changing the scaleview, i.e. when zooming or panning. For this much of the above code would be used to create the new images. See this post for examples of adding and replacing varying NamedImage to a Chart! (The relevant portion is close to the end about the marker images!)

事实上,我找到了最好的解决方案,并添加了第二个答案.

In fact I found that way the best solution and have added a second answer.

这篇关于如何将图像设置为沿图表轴或沿图表轴放置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆