在VB.NET中绘制三点圆弧

在VB.NET中绘制三点圆弧,.net,vb.net,winforms,gdi+,.net,Vb.net,Winforms,Gdi+,我正在尝试创建一个简单的界面(如画图)来绘制一些基本形状,如直线、圆和圆弧。我已经算出了直线和圆,但是我很难获得绘制圆弧的理想效果。我现在正在使用.NET中的graphics.Draw…方法,但可能愿意尝试另一种本机方法 我希望创建一个功能,让用户选择起点、终点和“半径”。但是,我希望“半圆”能接触到所有三点。在图片(从应用程序中拍摄)之后,Pt5通过用户的三次单击进行计算,并设置圆弧的“半径”。图像显示圆的中心位于Pt4上,但理想情况下,圆心将通过边缘处的Pt1和Pt2进行计算 一旦计算出圆心

我正在尝试创建一个简单的界面(如画图)来绘制一些基本形状,如直线、圆和圆弧。我已经算出了直线和圆,但是我很难获得绘制圆弧的理想效果。我现在正在使用.NET中的
graphics.Draw…
方法,但可能愿意尝试另一种本机方法

我希望创建一个功能,让用户选择起点、终点和“半径”。但是,我希望“半圆”能接触到所有三点。在图片(从应用程序中拍摄)之后,
Pt5
通过用户的三次单击进行计算,并设置圆弧的“半径”。图像显示圆的中心位于
Pt4
上,但理想情况下,圆心将通过边缘处的
Pt1
Pt2
进行计算

一旦计算出圆心,我想用它来创建圆弧的边界(
DrawArc(Pens.Black,CInt(center.X-Radius),CInt(center.Y-Radius),CInt(Radius*2),CInt(Radius*2),?,?)
)并通过点的投影沿着
Pt1
Pt2
直线“切割”圆

以下是我对上述线条/圆圈的计算(抱歉,问题太长了……):


所以我们都在同一个页面上,
DrawArc
方法有几个重载,但我将使用这个重载

Public Sub DrawArc(pen As System.Drawing.Pen, 
                   x As Single, 
                   y As Single, 
                   width As Single, 
                   height As Single, 
                   startAngle As Single,
                   sweepAngle As Single)
为了使用它,我们需要计算包含圆弧的边界矩形(如果它被绘制为完整的椭圆)、开始扫掠的角度以及圆弧的中心角度

对于以下内容,用户以更常见的方式定义三个圆弧点:圆心、起点和角度。也就是说,第一次单击定义中心,第二次单击确定起点,第三次单击确定圆弧跨越的角度。将其应用于其他方法很容易,但我使用的方法有最简单的数学解释

第一次单击时,我们将鼠标位置记录到变量
center
中。这是我们的弧的中心

在第二次单击时,我们将鼠标位置记录到变量
start
中。这一点为我们提供了两个关键信息,半径和到起点的角度。我们使用毕达哥拉斯定理(也称为距离公式)计算半径,如下所示:

r = Math.Sqrt(Math.Pow(start.X - center.X, 2) + Math.Pow(start.Y - center.Y))
为了计算角度,我们可以使用Δy/Δx的反正切

theta = Math.Atan((start.Y - center.Y) / (start.X - center.X))
(我将把它留作练习,让您检查
(start.X-center.X)=0
,并确定它是否为+/-π/2。)

我们现在也有足够的信息来计算圆弧的边界矩形。因为圆弧是圆的,所以我们的盒子是圆的

x = center.X - r
y = center.Y - r
width = 2 * r
height = 2 * r
当用户第三次单击时(或者实际上每当鼠标移动时),我们将值存储到
角度
变量中。现在,我们需要做的就是计算该点的角度,因为我们正在绘制一个圆弧段。第二个角度的计算方法与前一个相同:

alpha = Math.Atan((angle.Y - center.Y) / (angle.X - center.X))
(请记住,与前面一样,要检查
(angle.X-center.X)=0

现在我们可以通过减去

sweep = theta - alpha
我们现在有足够的信息,可以使用我们计算的参数调用
DrawArc
方法:

g.DrawArc(Pen.Black, x, y, width, height, theta, sweep)
最后几点想法:

  • 此方法将始终从起点逆时针绘制圆弧 角度
  • center
    start
    end
    变量都是
    PointF
    ,您需要根据需要进行转换。我删除了转换和捕获逻辑,使上面的代码更容易理解
  • 所有其他变量均为
    单个
    。您需要将
    Atan
    函数的结果转换为
    Single
  • 如果在计算反正切时Δx为0,则可以通过比较y值来判断角度是正还是负。如果
    (center.Y
    ,那么你知道它是+π/2。 -您可能还应该检查半径是否为0

    • 所以我们都在同一个页面上,
      DrawArc
      方法有几个重载,但我将使用这个重载

      Public Sub DrawArc(pen As System.Drawing.Pen, 
                         x As Single, 
                         y As Single, 
                         width As Single, 
                         height As Single, 
                         startAngle As Single,
                         sweepAngle As Single)
      
      为了使用它,我们需要计算包含圆弧的边界矩形(如果它被绘制为完整的椭圆)、开始扫掠的角度以及圆弧的中心角度

      对于以下内容,用户以更常见的方式定义三个圆弧点:圆心、起点和角度。也就是说,第一次单击定义中心,第二次单击确定起点,第三次单击确定圆弧跨越的角度。将其应用于其他方法很容易,但我使用的方法有最简单的数学解释

      第一次单击时,我们将鼠标位置记录到变量
      center
      中。这是我们的弧的中心

      在第二次单击时,我们将鼠标位置记录到变量
      start
      中。这一点为我们提供了两个关键信息,半径和到起点的角度。我们使用毕达哥拉斯定理(也称为距离公式)计算半径,如下所示:

      r = Math.Sqrt(Math.Pow(start.X - center.X, 2) + Math.Pow(start.Y - center.Y))
      
      为了计算角度,我们可以使用Δy/Δx的反正切

      theta = Math.Atan((start.Y - center.Y) / (start.X - center.X))
      
      (我将把它留作练习,让您检查
      (start.X-center.X)=0
      ,并确定它是否为+/-π/2。)

      我们现在也有足够的信息来计算圆弧的边界矩形。因为圆弧是圆的,所以我们的盒子是圆的

      x = center.X - r
      y = center.Y - r
      width = 2 * r
      height = 2 * r
      
      当用户第三次单击时(或者实际上每当鼠标移动时),我们将值存储到
      角度
      变量中。现在,我们需要做的就是计算该点的角度,因为我们正在绘制一个圆弧段。第二个角度的计算方法与前一个相同:

      alpha = Math.Atan((angle.Y - center.Y) / (angle.X - center.X))
      
      (请记住,与前面一样,要检查
      (angle.X-center.X)=0

      现在我们可以通过减去

      sweep = theta - alpha
      
      我们现在有足够的信息