Jump to content

Recommended Posts

Posted

Hi,

I'm struggling to develop an algorithm to render a ring. Two concentric circles with a filled area between them. 

Already spent several days, but ... :( So, I'll appreciate if someone could help me.

The easiest (obvious) approach drawing a number of circles doesn't work because there are many unfilled pixels, between them. That is obvious as well and is a consequence of the digitization.

My function is based on the Midpoint Circle Algorithm https://en.wikipedia.org/wiki/Midpoint_circle_algorithm as uGFX draw/fill circle functions are based as well. The FillRing algorithm draws lines instead of dots only, trying to calculate the start and end points. For most of the lines is easy, but for some of them is not. The troubles appears when the circles (drawing) are in a different octets, excepts the top/bottom part (defined by r_out - r_in), which is the easiest part.

Posted

Hi,

We certainly can't help you without you providing your algorithm. If it's a small issue we might be able to help you or to give you certain pointers.
Developing a dedicated algorithm for this is definitely the right approach as assembling the ring from other existing primitives will result in issues as you mentioned.

Depending on your application / use-case you might be able to use the new gdispDrawDualCircle() function that was added 17 hours ago: 

 

Posted

As you found the trick is when the octants change. Even if the gdispFillDualCircle() is not suitable you should be able to derive something from it that will work for you. gdispFillDualCircle() also uses (a variant optimisation of) the Midpoint algorithm so it is very fast.

Posted

Joel, inmarket

Thank you very much. The  gdispDrawDualCircle()  is exactly what I was looking for :) .

In order to make it exactly FillRing(), I just removed the third line in the #define DRAW_DUALLINE(yval, r1, r2),

i.e. "g->p.x = x-r2;   g->p.x1 = x+r2;   g->p.color = color2; hline_clip(g);    \"  and it was done.

But what about the definition in gdisp.h

void gdispGFillDualCircle(GDisplay *g, coord_t x, coord_t y, coord_t radius1, color_t color1, coord_t radius2, color_t color2);
    #define gdispFillDualCircle(x,y,r,c)                    gdispGFillDualCircle(GDISP,x,y,r1,c1,r2,c2)

I think it shall be

#define gdispFillDualCircle(x,y,r1,c1,r2,c2)                    gdispGFillDualCircle(GDISP,x,y,r1,c1,r2,c2)

isn't it?

And I noticed extra pixels on the poles(E, S, W, N) of the both circles. The inner has on East and West only, perhaps the North and South are covered by top and bottom part of the outer circle. So, I drew two circles over the ring using the midpoint algorithm. Attached is the function and both pictures. Sorry for the pictures bad quality, but the differences are clearly visible.

Ring.zip

Posted

You are right about the macro. We will fix that asap.

Yes this is not exactly the midpoint algorithm. This is a first rather than a second derivative using the same reasoning. It is slightly less accurate than the midpoint algorithm however even the µGFX circle algorithm is not quite right either. In practice the true midpoint algorithm has some visual anomalies when rendered on low resolution screens that relate to the way integer rounding works. The µGFX circle algorithm has made some accuracy compromises in order to avoid those issues but is still very close to the midpoint algorithm.

The reason the ring uses a different algorithm again is that swapping the quadrants would require a square root operation to do it properly. By making a slight compromise on accuracy we avoid that expensive computation.

At some point in the future I may look at performing the same work on the ring code that was performed on the µGFX general circle algorithm but that is definitely not high priority. It is very time consuming to adjust that pixel here and there to get the best looking result at a range of sizes and resolutions.

Posted

I see inmarket. But the nowadays embedded systems normally are powerful enough. Especially in terms of calculating power/speed. For example my system is with cortex-m4 at 120MHz and integrated floating point. Might be better if there is an option to choose better presentation at the corresponding resources cost of course.

So, are you not eager to make the ring a progress bar/slider? :)

Posted

Note that having a powerful processor doesn't mean that you can use the available resources for the GUI. There are more than plenty systems out there that run µGFX on very powerful & capable hardware that benefit from the fact that µGFX uses only a very small part of those resources so the rest is available to the actual job done (the stuff other than the GUI).

 

11 minutes ago, wctltya said:

So, are you not eager to make the ring a progress bar/slider? :)

We are working on that. That's why @inmarket wrote that new gdispGFillDualCircle() in first place.

Posted
3 minutes ago, Joel Bodenmann said:

Note that having a powerful processor doesn't mean that you can use the available resources for the GUI.

Sure, but in my particular case it is a dedicated HMI, so a communication with the main system is the only tasks run a side of the GUI.

5 minutes ago, Joel Bodenmann said:

We are working on that. That's why @inmarket wrote that new gdispGFillDualCircle() in first place

That is a very nice news. Can't wait to have it.

Posted

With drawing algorithms we generally code for the lowest common denominator. ie. integer algorithms with as few multiply and divides as possible.

To have a seperate "expensive" version just does not make sense. It is twice the code, twice the potential bugs, twice the maintenance etc. If and when we spend more time on it, it will be to improve the accuracy for all platforms.

The issues identified are around the integer approximation and its interaction with the midpoint algorithm (note the x axis end-points that you commented on). For the ring you also need the corresponding reverse derivitive approximation for when the octants are not aligned between the two circles.

We would really love it if you had time to look at this for us. Unfortunately we just have too much on our development agenda to look at improving this anytime soon.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...