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:


This is not an arc. An arc is a curve, that is part of the circumference of a circle. B4XPath is drawing a sector.
 

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:



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.
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…