Announcement

Collapse
No announcement yet.

Partial Pie Slice / Wide Arc

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Partial Pie Slice / Wide Arc

    Hello!

    I need to draw a wide arc, or a partial pie slice. Imagine drawing a pie slice, and then covering the inner portion with the background color. The end result should be a wide arc with an inner and outer radius, drawn between two angles and with a given color. At the moment, I'm accomplishing this as described - use the gfx_PieSlice function and then draw a black pie slice over top, but this results in nasty flicker when large sections must be redrawn, as you can see a little of the original color slice before the black slice fully covers it up. Naturally, it's even worse if I want to draw anything meaningful inside that black region, as the flicker is horrendous.

    Is there a better way to do this? I've tried to find the source for the gfx_PieSlice function to modify for what I need, but I haven't been able to locate it.

    Thanks,

    RJ

  • #2
    I don't know if it's "better," but you can accomplish this via a polygon fill. Whether or not this is better may depend on what the limiting factor is (draw vs computation).

    I did something similar when making an interface for Garmin smartwatches when they didn't support fat arcs. Example below, using 60 points to generate the arcs.

    Code:
    #inherit "4DGL_16bitColours.fnc"
    func main()
    
        gfx_ScreenMode(LANDSCAPE_R) ; // change manually if orientation change
        gfx_Cls();
        drawFattyArc(100,100,30,40,0,90,WHITE);
        drawFattyArc(100,100,40,50,15,115,BLUE);
        drawFattyArc(100,100,50,60,30,130,RED);
        repeat                      // maybe replace
        forever                     // this as well
    
    endfunc
    
    func drawFattyArc(var xCenter, var yCenter, var innerRadius, var outerRadius, var startAngle, var endAngle, var fillColor)
        var xPoints[60];
        var yPoints[60];
        var stepNum, curAngle, curX, curY;
        gfx_MoveTo(xCenter,yCenter);
        for(stepNum := 0;stepNum < 30;stepNum++)
            curAngle := startAngle + stepNum*(endAngle - startAngle) / 29;
            gfx_OrbitInit(&curX,&curY);
            gfx_Orbit(curAngle,outerRadius);
            xPoints[stepNum] := curX;
            yPoints[stepNum] := curY;
        next
        for(stepNum := 0;stepNum < 30;stepNum++)
            curAngle := endAngle -(stepNum*(endAngle - startAngle) / 29);
            gfx_OrbitInit(&curX,&curY);
            gfx_Orbit(curAngle,innerRadius);
            xPoints[stepNum + 30] := curX;
            yPoints[stepNum + 30] := curY;
        next
        gfx_PolygonFilled(60,xPoints,yPoints,fillColor);
    endfunc

    Comment


    • #3
      Hello RJ,

      The flickering occurs if you are frequently updating the area of the screen
      with different colors. This is highly noticeable when using colors in contrast
      with each other (e.g bright and dark colors).

      A great solution was provided by mspringer which only draws the required
      area needed for a custom project.
      Thank you mspringer for sharing your code.

      Best Regards,
      Kevin

      Comment


      • #4
        mspringer, thanks for the idea. I actually had already tried this (with a shockingly similar implementation), but found that the CPU load is much too high to make that a real solution in my case. I need to update the arc at 10Hz+. I'm already only re-drawing the small portion of the arc that changes each time (only a few degrees at a time usually), except when the arc needs to change color, in which case naturally the entire thing must be re-drawn.

        Kevin, is there a more efficient solution to this issue? Obviously (at least I hope) the gfx_PieSlice function is doing something much more efficient at a low level. Can we implement a similar low-level function to handle this?

        Thanks!

        RJ

        Comment


        • #5
          Hmm, well then this does take a little more thinking. I'm curious if there's anything more efficient occurring in PieSlice as well. If not however, I have a few other questions/thoughts. I would expect if you could get the computation time down with a polygon fill, you'd remove your flickering since you're drawing that region in a single operation.
          • Are your arcs always in the same location (center and radii), and can you define pre-set angular draw increments? If so, you could pre-compute all of the polygon locations ahead of time and then use fast array operations to get the correct slices and draw the fills.
          • If the arcs are always in the same location, but could have run time varying radii, you could still pre-populate arrays with cos(angle) , sin (angle) computations, and run an array multiply on that to get the r*sin(angle) , r*cos(angle) points for the polygon.
          • Similar to the first point, if the arcs are always the same location/size, you could create a .gci of the incremental arcs and draw using img_ functions, which are quite fast.
          That's all I've got. Good luck!

          Comment


          • #6
            Thanks for the thoughts! I wrote some pre-compiled sin/cos tables, but I'm guessing the built-in COS/SIN functions are also table lookups, as I get essentially identical execution time between the two.

            In this case I could live with fixed radii, so I could go a step further and pre-compute the full locations, but those would get to be some large arrays.

            I'm really shooting for 1-degree resolution, which isn't helping my case - the polygons could have 720 points! Even at 2-degree resolution, they look really ragged.

            The img_ function approach might be worth a shot... I'll look into that.

            Thanks!

            Comment

            Working...
            X