Bug? B4XPath Not Drawing Arcs

keirS

Well-Known Member
Licensed User
Longtime User
This snippet of code:

B4X:
Dim APath As B4XPath
APath.InitializeArc(ARCStartPoint.XCoord,ARCStartPoint.YCoord,CalcDistance(ARCStartPoint,ArcEndPoint1),10,350)
 cvsTemp.DrawPath(APath,xui.Color_Red,False,1)
 cvsTemp.DrawCircle(ArcEndPoint1.XCoord,ArcEndPoint1.YCoord,5,xui.Color_Red,True,1)
 cvsTemp.DrawCircle(ARCEndPoint2.XCoord,ARCEndPoint2.YCoord,5,xui.Color_Red,True,1)

Draws this:
Sector Not Arc.PNG


This is not an arc. An arc is a curve, that is part of the circumference of a circle. B4XPath is drawing a sector.
1200px-Circle_slices.svg.png
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
The path is defined by the arc. DrawPath draws closed shapes so you are getting a sector.

Note that you can draw an arc with BitmapCreator.DrawArc:
B4X:
Dim bc As BitmapCreator
bc.Initialize(ImageView1.Width, ImageView1.Height)
bc.DrawArc(50, 50, 50, xui.Color_Red, False, 2dip, 0, 90)
bc.SetBitmapToImageView(bc.Bitmap, ImageView1)
 

keirS

Well-Known Member
Licensed User
Longtime User
BitmapCreator won't work for what I want to do.

So I came up with this:

B4X:
Sub DrawArc(CVS As B4XCanvas,CenterPoint As Point,Radius As Float,StartAngle As Float, EndAngle As Float,StrokeWidth As Float,Color As Int)
    Dim ArcAngle As Float = EndAngle - StartAngle
    Dim ArcLength As Float = (ArcAngle/360)  * (2 * (cPI * Radius))
    Dim PixelPerDegree As Int  = Round(ArcLength / ArcAngle) +1
    Dim OuterPoint360 As Point
    Dim InnerPoint360 As Point
    OuterPoint360.Initialize(CenterPoint.XCoord - Radius,CenterPoint.YCoord)
    InnerPoint360.Initialize(OuterPoint360.XCoord - StrokeWidth,OuterPoint360.YCoord)
    
    Dim Degrees As Float = StartAngle
    
    
    Do While Degrees <= EndAngle
        Dim Pts As List
        Pts.Initialize
        For Cntr = 1 To PixelPerDegree
            Dim P As Point = RotatePoint(OuterPoint360,CenterPoint,Degrees + ((1/PixelPerDegree) * Cntr))
            Dim P2 As Point = RotatePoint(InnerPoint360,CenterPoint,Degrees + ((1/PixelPerDegree) * Cntr))
            CVS.DrawLine(P.XCoord,P.YCoord,P2.XCoord,P2.YCoord,Color,1)
        Next
        Degrees = Degrees + 1
        
    Loop
End Sub

Sub RotatePoint(PointToRotate As Point, CenterPoint  As Point, AngleInDegrees As Double) As Point

    Dim angleInRadians As Double  = AngleInDegrees * (cPI / 180)
    Dim CosTheta As Double = Cos(angleInRadians)
    Dim SinTheta As Double = Sin(angleInRadians)
    Dim P As Point
    P.Initialize(-1,-1)
    P.XCoord = (CosTheta * (PointToRotate.XCoord - CenterPoint.XCoord) - SinTheta * (PointToRotate.YCoord - CenterPoint.YCoord) + CenterPoint.XCoord)
    P.YCoord = (SinTheta * (PointToRotate.XCoord - CenterPoint.XCoord) + CosTheta * (PointToRotate.YCoord - CenterPoint.YCoord) + CenterPoint.YCoord)
    Return P
   
End Sub


Calling DrawArc

B4X:
Dim CenterPoint As Point
    CenterPoint.Initialize(300,300)

    DrawArc(cvsPoints,CenterPoint,100,135,225,2,XUI.Color_Red)

Gives this:

arc2.PNG


I pretty sure there is a standard algorithm for calculating the pixels per degree required but I couldn't find it and I am sure my calculation is unnecessary in a lot of situations and is not very efficient. But it does seem to work.
 
Top