gpt4 book ai didi

c# - 如何将图像设置为图表轴或沿图表轴设置?

转载 作者:太空狗 更新时间:2023-10-30 00:22:52 25 4
gpt4 key购买 nike

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

我曾尝试使用图像注释,但随着图表区域的变化,注释尺寸保持不变。另外,关注鼠标位置的滚动缩放显然对注释没有影响。

最接近的方法是使用图像作为图表区域的背景。这会随着图表区域的变化自动缩放图像,但滚动缩放对背景图像没有影响。此外,理想的情况是背景清晰,以避免模糊数据绘图点。我可以编辑图像,使其具有较大的透明部分,底部只有一条彩色 strip ,但即便如此,该 strip 可能会遮盖较低强度的数据点。

作为注释和背景的光谱: enter image description here

注释未缩放,背景缩放良好: enter image description here

注释和背景都不随缩放缩放: enter image description here

最佳答案

这是个好主意。

最简单的方法是在图表的 Paint 事件中绘制图像,也许是 PrePaint

enter image description here

让我们开始工作.. 我们将使用 DrawImage允许我们缩放和裁剪的重载。为此,我们需要两个矩形。

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

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

这两个函数将有助于:

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

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

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

您可以根据自己的喜好选择高度..

下一个挑战是源矩形。

如果不缩放,它只会是:

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

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

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

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

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

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

一些注意事项:

  • 当然我会推荐使用图像资源而不是总是从磁盘加载!

  • 绘图将始终覆盖数据点和网格。你也可以..

  • 选择不同的最小值以腾出空间

  • 缩小图片

  • 将它移到 x 轴标签下方

  • 使图像半透明

  • 使 x 轴足够粗,可以容纳图像条:ax.LineWidth = 10

对于后一种解决方案,您可能希望根据缩放状态偏移 y 位置。快速而肮脏:int yoff = (ax.ScaleView.IsZoomed ? 12 : 5);。为避免黑色条纹也使轴透明或 chart.BackColor ..

更新:

您也可以恢复使用 StripLine。它可以缩放其 BackgroundImage 并且您必须在每次更改缩放 View (即缩放或平移时)时创建合适的图像。为此,上面的大部分代码将用于创建新图像。参见 this post有关向图表添加和替换不同的 NamedImage 的示例! (有关标记图像的相关部分已接近尾声!)

事实上,我发现这种方式是最好的解决方案,并添加了第二个答案。

关于c# - 如何将图像设置为图表轴或沿图表轴设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49991598/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com