How to draw circular arcs in VB.NET

2019-08-29 12:21发布

I have to generate the following figure according to user fed values. How do I go about drawing the arcs (B-C-F as in figure, circular in nature) given their start point & end point (B & F respectively) & the height from the segment BF? I can do some geometric calculations & get the radius & all, but how do I draw the arc?

enter image description here

I have tried using the Graphics.DrawCurve() method, but it doesn't work as expected. How can I make this method work for circular arcs? Any other workaround is also welcome.

2条回答
看我几分像从前
2楼-- · 2019-08-29 13:09

Got it! Thanks @Mitch & @Idle_Mind

Using the builtin DrawArc method of Graphics

Friend Function draw_tank() As Boolean

    ' Create pen. 
    Dim blackPen As New Pen(Color.Black, 3)

    ' Create rectangle to bound ellipse. 
    Dim rect As New Rectangle(100, 100, 200, 200)
    ' Keeping the width & length same (200) we get a circle

    ' Create start and sweep angles on ellipse. 
    Dim startAngle As Single = 225.0F
    Dim sweepAngle As Single = 90.0F

    ' Draw arc to screen.
    Dim myarc As Graphics = Me.CreateGraphics
    myarc.DrawArc(blackPen, rect, startAngle, sweepAngle)

    Return True
End Function

Suggestions/Improvements welcome.

Note - This isn't the actual function from my code.

查看更多
三岁会撩人
3楼-- · 2019-08-29 13:17

From my comment:

If you have computed the necessary radius to generate the curve, then simply draw the entire circle with Graphics.DrawEllipse(), but use Graphics.SetClip() and pass a rectangle using the points B and F as a side and computing the other two points using the height C. This will clip the entire circle to just the part visible within that rectangle. Then call Graphics.ResetClip() and draw the rest of the lines. Repeat the SetClip() trick to draw the curve at the bottom as well.

Here's a proof of concept for the top curve thru B, C, and F.

I used the formulas provided by Donna Roberts at Investigative Circle Activity Using Three Points.

Here's a screenshot:

Partial Circle thru Three Points

...and the code that produced it:

Public Class Form1

    Private B As New Point(50, 100)
    Private F As New Point(250, 100)
    Private DistanceFromBF As Integer = 50

    Private Sub Form1_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
        If B.Y = F.Y Then
            Dim C As New Point(B.X + (F.X - B.X) / 2, B.Y - DistanceFromBF)
            Dim ctr As Point
            Dim rad As Double
            CircleFromPointsOnCircumference(B, C, F, ctr, rad)

            Dim rc As New Rectangle(ctr, New Size(1, 1))
            rc.Inflate(rad, rad)
            e.Graphics.DrawRectangle(Pens.Black, rc)

            Dim clip As New Rectangle(New Point(B.X, B.Y - DistanceFromBF), New Size(F.X - B.X, DistanceFromBF))
            e.Graphics.SetClip(clip)
            e.Graphics.DrawEllipse(Pens.Green, rc)

            e.Graphics.ResetClip()
            DrawPoint(B, e.Graphics, Color.Red)
            DrawPoint(C, e.Graphics, Color.Red)
            DrawPoint(F, e.Graphics, Color.Red)
            DrawPoint(ctr, e.Graphics, Color.Green)
        End If
    End Sub

    Private Sub DrawPoint(ByVal pt As Point, ByVal G As Graphics, ByVal clr As Color)
        Dim rc As New Rectangle(pt, New Size(1, 1))
        rc.Inflate(3, 3)
        Using brsh As New SolidBrush(clr)
            G.FillEllipse(brsh, rc)
        End Using
    End Sub

    Private Sub CircleFromPointsOnCircumference(ByVal ptA As Point, ByVal ptB As Point, ByVal ptC As Point, ByRef Center As Point, ByRef Radius As Double)
        Dim mR As Double = CDbl(ptA.Y - ptB.Y) / CDbl(ptA.X - ptB.X)
        Dim mT As Double = CDbl(ptC.Y - ptB.Y) / CDbl(ptC.X - ptB.X)
        Dim X As Double = (mR * mT * (ptC.Y - ptA.Y) + mR * (ptB.X + ptC.X) - mT * (ptA.X + ptB.X)) / CDbl(2) * (mR - mT)
        Dim Y As Double = CDbl(-1) / mR * (X - CDbl(ptA.X + ptB.X) / CDbl(2)) + (CDbl(ptA.Y + ptB.Y) / CDbl(2))
        Center = New Point(X, Y)
        Radius = Math.Sqrt(Math.Pow(ptA.X - Center.X, 2) + Math.Pow(ptA.Y - Center.Y, 2))
    End Sub

End Class
查看更多
登录 后发表回答