绘制贝塞尔曲线的半弧

时间:2014-08-06 10:17:55

标签: c# graphics bezier

我想将贝塞尔曲线分成两部分。例如,如果点(100,100)和(200,100)与控制点(150,150)和(175,150)之间存在贝塞尔曲线,则曲线应以两种不同颜色(例如红色和绿色)着色,一个颜色从(100,100)到(150,100)表示红色,另一种颜色从(150,100)到(200,100)表示绿色。

这是我绘制bezier样条曲线的代码:

void Form1_Paint(object sender, PaintEventArgs e)
        {
            Point startPoint = new Point(100, 100);
            Point endPoint = new Point(200, 100);
            Point ctPoint1 = new Point(150, 150);
            Point ctPoint2 = new Point(175, 150);
            GraphicsPath gp = new GraphicsPath();
            gp.AddLine(new Point(100, 0), new Point(100, 100));
            gp.AddBezier(startPoint, ctPoint1, ctPoint2, endPoint);
            gp.AddLine(new Point(200, 100), new Point(200, 0));
            gp.AddLine(new Point(100, 0), new Point(200, 0));
            e.Graphics.FillPath(Brushes.Aqua, gp);
}

我想用两种颜色填充它,就像我上面解释的那样。

Result

期望的结果: Desired Result

我怎样才能实现这个目标

编辑:

我已经检查了一些用于分割贝塞尔曲线enter link description here的链接,但它告诉我找到曲线的中点而不是我的情景,我正在寻找绘制半贝塞尔曲线。

已知值:两点及其控制点在两点之间绘制贝塞尔曲线

预期结果:从起点到中点绘制贝塞尔曲线的一部分,从中点到终点绘制另一部分。

2 个答案:

答案 0 :(得分:1)

如果你脑海中贝塞尔曲线的“中点”实际上是贝塞尔曲线上x = 150的点,那么仍然可以通过分析计算它。由于贝塞尔曲线仅为3阶,我们可以计算对应于中点的参数't'(例如,使用Cardano公式)。获得中点参数后,可以使用de Cateljau算法查找两条分割曲线的控制点。将两条分割曲线作为贝塞尔曲线后,可以根据需要绘制两个区域。

以下是分割曲线的结果控制点:

第一条分割曲线:(100,100)(120.196418101,120.196418101),(136.313883161,132.234930120)和(150.000000000,136.115536​​056)。

第二条分割曲线:(150.000000000,136.115536​​056),(170.196418101,141.842093918),(185.098209050,129.803581899)和(200,100)。

顺便说一句,“中点”的参数t约为0.403928。

对于具有控制点P0,P1,P2和p3的三次贝塞尔曲线,给定分裂参数t,分裂曲线的控制点计算如下(使用De Casteljau算法)

1)将Q0,Q1和Q2计算为
   Q0 =(1-t)* P0 + t * P1
   Q1 =(1-t)* P1 + t * P2
   Q2 =(1-t)* P2 + t * P3

2)将R0和R1计算为
   R0 =(1-t)* Q0 + t * Q1
   R1 =(1-t)* Q1 + t * Q2

3)将S0计算为S0 =(1-t)* R0 + t * R1。这将是曲线上的分割点

4)第一个分割曲线的控制点是P0,Q0,R0和S0,第二个分割曲线的控制点是S0,R1,Q2和P3。

答案 1 :(得分:-1)

我使用了Region.Exclude方法和GraphicsPath.GetBounds方法

代码:

    //Creating graphics path for drawing bezier spline
    GraphicsPath gp = new GraphicsPath();
    gp.AddLine(new Point(100, 0), new Point(100, 100));
    gp.AddBezier(startPoint, ctPoint1, ctPoint2, endPoint);
    gp.AddLine(new Point(200, 100), new Point(200, 0));
    gp.AddLine(new Point(100, 0), new Point(200, 0));

    //Dividing the path into two regions
    Rectangle bounds=Rectangle.Round(gp.GetBounds());
    Region left = new Region(gp);
    left.Exclude(new Rectangle(bounds.Left, bounds.Top, (int)(bounds.Width / 2), bounds.Height));

    Region right = new Region(gp);
    right.Exclude(new Rectangle((int)(bounds.Left + bounds.Width / 2), bounds.Top, (int)(bounds.Width / 2), bounds.Height));

    //Drawing divided regions
    e.Graphics.FillRegion(Brushes.Black, left);
    e.Graphics.FillRegion(Brushes.Aqua, right);

说明:

  1. 构造绘制贝塞尔样条曲线的路径
  2. 为路径创建区域
  3. 将路径分成两个相等的区域。
  4. 使用e.Graphics.FillRegion方法填充贝塞尔曲线的所需部分