GDI +曲线"溢出"

时间:2015-06-11 21:22:48

标签: c# graphics graph gdi+

我目前正在使用GDI +绘制折线图,​​并使用Graphics.DrawCurve来平滑线条。问题是曲线并不总是与我提供的点匹配,这使曲线在某些点上长出图形框架,如下所示(红色为Graphics.DrawLines,绿色为{{ 1}})。

graph

我将如何解决这个问题?

2 个答案:

答案 0 :(得分:6)

最简单的解决方案是设置张力:

enter image description here

使用默认张力绘制绿色曲线,蓝色曲线设置张力Task<T>

0.1f

您需要测试什么是最佳折衷方案,private void panel1_Paint(object sender, PaintEventArgs e) { e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; e.Graphics.DrawLines(Pens.Red, points.ToArray()); e.Graphics.DrawCurve(Pens.Green, points.ToArray()); e.Graphics.DrawCurve(Pens.Blue, points.ToArray(), 0.1f); } 仍然可以,0.2f已经透支了很多..

要获得真正好的解决方案,您需要使用DrawBeziers。这将允许您绘制可以通过点的曲线,而无需任何透支,并完全控制曲线的半径;但要这样你就需要找到&#39;,即计算 0.3f,这不过是微不足道的......:

enter image description here

这个结果绝不是完美的,但已经足够复杂了......我已经以相同的颜色显示了control points及其各自的curve points。对于每个点,都有传入传出控制点。对于平滑曲线,它们需要在曲线点上具有相同的切线/渐变。

我使用一些辅助函数来计算关于段的一些内容:

  • 渐变列表
  • 渐变迹象列表
  • 段长度列表
  • 点之间的水平和垂直间隙列表

main函数计算control points的数组,即bezier points,每对之间上一个下一个 { {1}}。

curve points事件中,它的使用方式如下:

control points

以下是我使用的功能:

Paint

最后是主要功能;在这里我做了一个区别:极值点(极小值和最大值)的控制点应该与点本身在同一高度。这样可以防止垂直溢出。它们很容易找到:它们的渐变迹象总是会有所不同。

其他点需要对传入和传出控制点具有相同的渐变。我使用段之间的平均值&#39;梯度。 (也许一个称重的平均值会更好......)然后我根据段长度来衡量它们的距离..

List<PointF> bezz = getBezz(points);

using (Pen pen = new Pen(Color.Black, 2f))
       e.Graphics.DrawBeziers(pen, bezz.ToArray());

请注意,对于具有相同x坐标的点的情况,我没有编码。所以这对于功能图表来说是可以的。但不是说,比如数字,例如分..

答案 1 :(得分:0)

也许你只是想看看“超越边界”问题,因为这不是超调问题,而是有界限。在这种情况下,您可以使用System.Drawing.Drawing2D.GraphicsPath对象确定曲线的实际边界:

GraphicsPath gp = new GraphicsPath();
gp.AddCurve(listOfPoints);
RectangleF bounds = gp.GetBounds();

您可以直接绘制GraphicsPath:

graphics.DrawPath(Pens.Black, gp);

就解决边界问题而言,线必然会超过某些轴上的顶点。当线条与边界对齐时,更容易看到这一事实。

鉴于以下几点:

为了使它们弯曲,它们必须以某种方式超出界限:

如果您永远不想超过它们的垂直边界,您可以简单地确保贝塞尔曲线手柄具有与顶点相同的Y值,但它们会在X上超调:

反之亦然:

你可以故意下冲到足以避免曲线过冲的方式。这可以通过交换贝塞尔手柄来完成,贝塞尔手柄可能位于线中心,顶点为: