draw a arc
Moderators: David Barker, Jerry Messina
draw a arc
hello,
how can i draw a arc with the ks0108. i can't find it in the graphic module.
thanks
how can i draw a arc with the ks0108. i can't find it in the graphic module.
thanks
If it isn't there then you'll have to roll your own.
I would start by looking up equations of circles, both Cartesian and using good old Pythagorus. This should help to derive an equation to work out coordinates.
With a bit of fiddling I'm sure you could produce a useful function that could draw arcs and sectors.
There may be functions already posted on the Nerdynet.
I would start by looking up equations of circles, both Cartesian and using good old Pythagorus. This should help to derive an equation to work out coordinates.
With a bit of fiddling I'm sure you could produce a useful function that could draw arcs and sectors.
There may be functions already posted on the Nerdynet.
depending on the ARC you want if its a quater circle look up Bresenham cirlce algo and only iterate a quarter. The circle algo in GLCD lib is bresh i beleive , so you could copy the function rename and mod for arc.
http://en.wikipedia.org/wiki/Midpoint_circle_algorithm to start you off
if you want a more complex curve look for the Bezier curve algo
http://en.wikipedia.org/wiki/B%C3%A9zier_curve to start you off there
for bezier cubic form is probably easiest to implement and most useful.
a simple arc can be made with either (cubic bezier make P1 and p2 the same a line midpoit to create an isoslies triange in coords)
Bresanham is faster to compute and better for a true circle (or part of) bezier (slpines) is better for sweeping curves.
http://en.wikipedia.org/wiki/Midpoint_circle_algorithm to start you off
if you want a more complex curve look for the Bezier curve algo
http://en.wikipedia.org/wiki/B%C3%A9zier_curve to start you off there
for bezier cubic form is probably easiest to implement and most useful.
a simple arc can be made with either (cubic bezier make P1 and p2 the same a line midpoit to create an isoslies triange in coords)
Bresanham is faster to compute and better for a true circle (or part of) bezier (slpines) is better for sweeping curves.
If you can read this you are too close
Hello Mast,
I assume you are after a circular arc? I wound up modifying a set of drawing routines in "the other compiler" for an SSD0323 Oled Driver, heres the bit of interest to you. Should be fairly easy to convert to SF basic. The sub call PIXELWIDTH_ON_OFF is just the actual pixel draw sub. If you're having problems with it let me know and i'll try to help - its been a while though!
Nathan
Edit: Next reply has actual code now
I assume you are after a circular arc? I wound up modifying a set of drawing routines in "the other compiler" for an SSD0323 Oled Driver, heres the bit of interest to you. Should be fairly easy to convert to SF basic. The sub call PIXELWIDTH_ON_OFF is just the actual pixel draw sub. If you're having problems with it let me know and i'll try to help - its been a while though!
Nathan
Edit: Next reply has actual code now
Ok, I got bored and it was bothering me that I hadn't done the code, so here it is.
Dependent upon Maths.bas and GLCD.bas
Edit: Reduced the amount of excess FP math as per Octal's suggestion
Dependent upon Maths.bas and GLCD.bas
Code: Select all
{
********************************************************************************
* Name : DrawArc *
* Purpose : Draws a circular arc section *
********************************************************************************
}
Sub DrawArc(xCentre As Word, yCentre As Word, radius As Word, xStart As Word, yStart As Word, xEnd As Word, yEnd As Word)
Dim ang1 As Float
Dim ang2 As Float
Dim tempfloat1 As Float
Dim tempfloat2 As Float
Dim xDraw As Word
Dim yDraw As Word
Dim tempword1 as word
Dim tempword2 as word
// Set the Granularity of the plot
// 0.03 is a bit fine (i.e. small gaps in arc), 0.02 is moderate, 0.01 is a bit coarser (i.e. certain points start to get heavy)
Const Granularity = 0.02
// Check Ang1
If xStart - xCentre = 0 Then
If yStart < yCentre Then
ang1 = 3 * 3.14 / 2
Else
ang1 = 3.14 / 2
EndIf
ElseIf yStart = yCentre Then
If xStart < xCentre Then
ang1 = 3.14
Else
ang1 = 0
EndIf
Else
If xStart > xCentre And yStart > yCentre Then // Quadrant 1
tempword1 = (yStart - yCentre)
tempword2 = (xStart - xCentre)
ang1 = tempword1 / tempword2
ang1 = atan(ang1)
EndIf
If xStart < xCentre And yStart > yCentre Then // Quadrant 2
tempword1 = (yStart - yCentre)
tempword2 = (xCentre - xStart)
ang1 = tempword1 / tempword2
ang1 = 3.14 - (atan(ang1))
EndIf
If xStart < xCentre And yStart < yCentre Then // Quadrant 3
tempword1 = (yCentre - yStart)
tempword2 = (xCentre - xStart)
ang1 = tempword1 / tempword2
ang1 = (atan(ang1)) + 3.14
EndIf
If xStart > xCentre And yStart < yCentre Then // Quadrant 4
tempword1 = (yCentre - yStart)
tempword2 = (xStart - xCentre)
ang1 = tempword1 / tempword2
ang1 = (2 * 3.14) - (atan(ang1))
EndIf
EndIf
// Check Ang2
If xEnd - xCentre = 0 Then
If yEnd < yCentre Then
ang2 = 3 * 3.14 / 2
Else
ang2 = 3.14 / 2
EndIf
ElseIf yEnd = yCentre Then
If xEnd < xCentre Then
ang2 = 3.14
Else
ang2 = 0
EndIf
Else
If xEnd > xCentre And yEnd > yCentre Then // Quadrant 1
tempword1 = (yEnd - yCentre)
tempword2 = (xEnd - xCentre)
ang2 = tempword1 / tempword2
ang2 = atan(ang2)
EndIf
If xEnd < xCentre And yEnd > yCentre Then // Quadrant 2
tempword1 = (yEnd - yCentre)
tempword2 = (xCentre - xEnd)
ang2 = tempword1 / tempword2
ang2 = 3.14 - (atan(ang2))
EndIf
If xEnd < xCentre And yEnd < yCentre Then // Quadrant 3
tempword1 = (yCentre - yEnd)
tempword2 = (xCentre - xEnd)
ang2 = tempword1 / tempword2
ang2 = (atan(ang2)) + 3.14
EndIf
If xEnd > xCentre And yEnd < yCentre Then // Quadrant 4
tempword1 = (yCentre - yEnd)
tempword2 = (xEnd - xCentre)
ang2 = tempword1 / tempword2
ang2 = (2 * 3.14) - (atan(ang2))
EndIf
EndIf
// draws anti-clockwise
Repeat
tempfloat1 = radius * (cos(ang1))
tempfloat2 = radius * (sin(ang1))
xDraw = xCentre + tempfloat1
yDraw = yCentre - tempfloat2
SetPixel(xDraw, yDraw)
ang1 = ang1 + Granularity
tempfloat1 = ang2 - 0.05
tempfloat2 = ang2 + 0.05
If ang1 > (2 * 3.14) Then
ang1 = 0
EndIf
Until ang1 > tempfloat1 And ang1 < tempfloat2
End Sub
Last edited by RangerBob on Wed Feb 03, 2010 9:45 am, edited 1 time in total.
Nice work,
but I think about two things:
1- Avoiding Floating points is mandatory if you want it to be quick enough, so you can use integers and move your floating point accordingly when interpreting results.
2- If the user wants to draw an arc dynamically to show some measurements for example, if he use this code intensively it will be really cpu intensive, and if he wants to use it just to draw an arc at background and later darw a line on top of it to show a level meter for example the best is to use simply a bitmap.
Regards
but I think about two things:
1- Avoiding Floating points is mandatory if you want it to be quick enough, so you can use integers and move your floating point accordingly when interpreting results.
2- If the user wants to draw an arc dynamically to show some measurements for example, if he use this code intensively it will be really cpu intensive, and if he wants to use it just to draw an arc at background and later darw a line on top of it to show a level meter for example the best is to use simply a bitmap.
Regards
Fair points,
Regards,
Nathan
Depends what you consider is quick enough really. In a typical application this was used with at an update rate of once per second on a 32mhz 4550, along with a bunch of other intensive operations and it barely taxed it (plenty of spare cycles left over). I could have avoided floats but maths is hard!octal wrote: 1- Avoiding Floating points is mandatory if you want it to be quick enough, so you can use integers and move your floating point accordingly when interpreting results.
Depends how big you want the meter to be . I specifically wrote this originally for exactly this type of application. The customer wanted a *big* meter though and the bitmap was huge 6k, I wrote this to save space in comparison (plus for flexibility)! This code is 4k. Swings and roundabouts really.octal wrote: and if he wants to use it just to draw an arc at background and later darw a line on top of it to show a level meter for example the best is to use simply a bitmap.
Regards,
Nathan
This might be Handy for you then:
Have fun No sense reinventing the wheel!
[edit] Fuzzy, lousy Pic of code in action; Darn you iPhone camera!
darker line is a trend line, brighter current. Couldn;t figure out how to do a quick and easy pointy top to line like yours!
Code: Select all
{
********************************************************************************
* Name : DrawLineAngle *
* Purpose : Draws a line at given angle in pelorus *
********************************************************************************
}
Public Sub DrawLineAngle(lineangle As Float, pencolor As Byte)
Dim sinresult As Float
Dim cosresult As Float
Dim pointerxf As Byte
Dim pointeryf As Byte
Dim pointerxb As Byte
Dim pointeryb As Byte
lineangle = (lineangle * 3.14) / 180
sinresult = sin(lineangle)
cosresult = cos(lineangle)
pointerxf = abs( PelCenterX - (PelRadOut - 4) * sinresult ) 'fx - outer radius
pointeryf = abs( PelCenterY + (PelRadOut - 4) * cosresult ) 'fy + outer radius
pointerxb = abs( PelCenterX - (PelRadIn + 2) * sinresult ) 'fx - inner radius
pointeryb = abs( PelCenterY + (PelRadIn + 2) * cosresult ) 'fy + inner radius
// Draw New Line
Pen.Color = pencolor
Line(pointerxb,pointeryb,pointerxf,pointeryf)
End Sub
[edit] Fuzzy, lousy Pic of code in action; Darn you iPhone camera!
darker line is a trend line, brighter current. Couldn;t figure out how to do a quick and easy pointy top to line like yours!