有没有办法获得stackcolumn图表栏的矩形?
这段代码片段是如何工作的,但它非常难看:
send: b'POST /forum/ucp.php?mode=login HTTP/1.1
Host: osu.ppy.sh
Accept-Encoding: identity
Content-Length: 70'
send: b'redirect=index.php&sid=&login=Login&username=USERNAME-HERE&password=PASSWORD-HERE'
reply: 'HTTP/1.1 200 OK'
header: Date
header: Content-Type
header: Transfer-Encoding
header: Connection
header: Set-Cookie
header: Cache-Control
header: Expires
header: Pragma
header: X-Frame-Options
header: X-Content-Type-Options
header: Server
header: CF-RAY
我会试着描述我的目的: 我想从各种测试结果创建一个图表,并将其作为HTML文件提供。生成的图表作为图像文件插入HTML文档中。现在,我想将图表区域的每个部分从图表链接到外部文档。由于图形是静态的,我只能使用“MAP Area”元素将任何区域作为HTML的链接。 “map”元素需要“矩形”或这些坐标。这就是我需要Bar的每个部分的协调员的原因。 我必须提到我还不熟悉Chart控件。
图形生成testweise。
[解决] 我得到了解决方案:
var points = new List<Point>();
for (int x = 0; x < chart.Size.Width; x++)
{
for (int y = 0; y < chart.Size.Height; y++)
{
var hp = chart.HitTest(x, y, false, ChartElementType.DataPoint);
var result = hp.Where(h => h.Series?.Name == "Cats");
if (result.Count() > 0)
{
points.Add(new Point(x, y));
}
}
}
var bottomright = points.First();
var topleft = points.Last();
此解决方法适用于stackcolumn,点从x轴= 0开始。 只需要手动设置PixelPointWidth属性以获得正确的宽度。我还没有找到一种方法来获得默认的条形宽度..
答案 0 :(得分:0)
这非常棘手,我真的希望我知道如何从某些图表功能中获取界限!
您的代码段实际上是解决方法的良好开端。我同意它有问题:
让我们逐一解决这些问题:
我发现有两件事不起作用:
HitTest
事件期间致电Pre/PostPaint
或发生可怕的事情,例如某些Series
失踪,异常或其他崩溃...... Series
的宽度的结果是关闭 1-2个像素。即使对于小图表,测试图表中每个像素的性能也会很糟糕,但是当您放大图表时会变得越来越糟。虽然这是相对容易预防的:
我们正在搜索的是每个DataPoint
的每个Series
的边界矩形。
矩形由左右或宽度加上顶部和底部或高度定义。
我们可以通过使用y值中的轴函数ValueToPixelPosition
和每个0
来获得顶部和底部的精确值点。这很简单便宜。
除此之外,我们仍然需要找到点的左和右边缘。要做到这一点,我们需要沿着零线进行测试。 (所有积分将在那里开始或结束!)
这大大减少了测试次数。
我决定分别对每个系列进行测试,每次都在0
进行测试。为了获得更好的性能,我们可以一次性完成所有工作。
这是一个为给定List<Rectangle>
返回Series
的函数:
List<Rectangle> GetColumnSeriesRectangles(Series s, Chart chart, ChartArea ca)
{
ca.RecalculateAxesScale();
List<Rectangle> rex = new List<Rectangle>();
int loff = s == chart.Series.Last() ? 2 : 0; ;
int y0 = (int)ca.AxisY.ValueToPixelPosition(0);
int left = -1;
int right = -1;
foreach (var dp in s.Points)
{
left = -1;
int delta = 0;
int off = dp.YValues[0] > 0 ? delta : -delta;
for (int x = 0; x < chart.Width; x++)
{
var hitt = chart.HitTest(x, y0 +off );
if (hitt.ChartElementType == ChartElementType.DataPoint &&
((DataPoint)hitt.Object) == dp)
{
if (left < 0) left = x;
right = x;
}
else if (left > 0 && right > left) break;
}
int y = (int)ca.AxisY.ValueToPixelPosition(dp.YValues[0]);
rex.Add(new Rectangle(left, Math.Min(y0, y),
right - left + 1 - loff, Math.Abs(y - y0)));
left = -1;
}
return rex;
}
一些注意事项:
我从RecalculateAxesScale
开始,因为在计算当前布局之前我们无法进行Hittest。
我使用辅助变量loff
来保存上一个Series
中宽度的偏移量。
我开始在最后一个x坐标处搜索,因为这些点应该按顺序排列。如果他们没有,因为您使用了有趣的x值或插入点,则可能需要从0
开始..
我使用y0
作为hittesting y和点'base的零值的基线。
我使用一点数学来获得正负y值的界限。
这是一个结构,用于保存所有Series
的矩形和代码以收集它们:
Dictionary<string, List<Rectangle>> ChartColumnRectangles = null;
Dictionary<string, List<Rectangle>> GetChartColumnRectangles(Chart chart, ChartArea ca)
{
Dictionary<string, List<Rectangle>> allrex = new Dictionary<string, List<Rectangle>>();
foreach (var s in chart.Series)
{
allrex.Add(s.Name, GetColumnSeriesRectangles(s, chart, ca));
}
return allrex;
}
每当我们添加点或调整图表大小时,我们需要重新计算矩形;每当轴视图改变时也是如此。 AxisViewChanged
,ClientSizeChanged
,Resize
的常用代码以及您添加或删除点的任何位置可能如下所示:
Chart chart= sender as Chart;
GetChartColumnRectangles(chart, chart.ChartAreas[0]);
让我们用Paint事件测试结果:
private void chart1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
chart1.ApplyPaletteColors();
foreach (var kv in ChartColumnRectangles)
{
{
foreach (var r in kv.Value)
g.DrawRectangle(Pens.Black, r);
}
}
}
这是在行动:
答案 1 :(得分:0)
好吧,我一直走这条路,对我来说,大的问题是'PixelPointWidth'的自定义属性就是这样-它是自定义的。除非已设置,否则无法检索。我需要物品的宽度-必须自己整理/计算。请记住,许多图表都可以平移/缩放,因此一旦走上这条路,就需要重新计算并为图表预涂事件设置它。
这是我做的一个粗略的小功能(比教育用途要冗长得多,并且没有错误处理:)):
private int CalculateChartPixelPointWidth(Chart chart, ChartArea chartArea, Series series)
{
// Get right side - takes some goofy stuff - as the pixel location isn't available
var areaRightX = Math.Round(GetChartAreaRightPositionX(chart, chartArea));
var xValue = series.Points[0].XValue;
var xPixelValue = chartArea.AxisX.ValueToPixelPosition(xValue);
var seriesLeftX = chart.Location.X + xPixelValue;
var viewPointWidth = Math.Round((areaRightX - seriesLeftX - (series.Points.Count * 2)) / series.Points.Count, 0);
return Convert.ToInt32(viewPointWidth);
}
这也是:
private double GetChartAreaRightPositionX(Chart chart, ChartArea area)
{
var xLoc = chart.Location.X;
return xLoc + (area.Position.Width + area.Position.X) / 100 * chart.Size.Width;
}
之所以这样计算,是因为我需要在普通图表项目对象(出于自己的目的而自己绘制)的顶部绘制一些图形叠加层。
在图表的“ prepaint”事件中,我需要计算与当前图表视图匹配的“ PixelPointWidth”(可能会被平移/缩放)。然后,我使用该值将图表自定义属性设置为match。 。 。这样正常的图表实体和MINE会正确对齐/缩放(确保我们位于正确的“ x”轴位置):
在我的绘画前事件中-在绘制图形实体之前,请执行以下操作:
// Pretty close scwag . . .
var viewPointWidth = CalculateChartPixelPointWidth(e.Chart, e.Chart.ChartAreas[0], e.Chart.Series[0]);
// Set the custom property and use the same point width for my own entities . .
chart1.Series[0].SetCustomProperty("PixelPointWidth", viewPointWidth.ToString("D"));
// . . . now draw my entities below . . .