(J'utilise SDL2)
SDL est une bibliothèque relativement petite pour "un accès bas niveau à l'audio, au clavier, à la souris, au joystick et au matériel graphique via OpenGL et Direct3D" Il est utilisé pour le développement de jeux et, dans mon cas, comme simple audiovisuel sortie et entrée souris + clavier. Ce n'est pas une "boîte à outils" comme GTK, Qt, wxWindows, etc. Mais c'est multi-plateforme.
En dehors de l'utilisation de trig ou de "l'équation d'un cercle", comment pourrais-je dessiner une courbe? Que diriez-vous des graphiques vectoriels généraux?
SDL est-il un point de départ approprié ou dois-je chercher ailleurs?
Si vous souhaitez écrire votre propre fonction de dessin de cercle, je suggère d'adapter algorithme de point médian à SDL2 en dessinant des pixels.
Les courbes seraient effectuées de la même manière, mais utiliseraient davantage un algorithme de dessin d'ellipses.
Les graphiques vectoriels réels commencent à devenir beaucoup plus compliqués, et vous devrez probablement trouver quelque chose qui rend les fichiers SVG, ce dont je ne suis pas sûr qu'il existe de nombreuses options pour SDL2.
Cependant, si vous préférez simplement avoir des fonctions avec lesquelles vous pouvez travailler, je vous suggère d'aller directement à SDL2_gfx à la place. Il a beaucoup plus de fonctions déjà implémentées avec lesquelles vous pouvez travailler.
Ceci est un exemple de l'algorithme du cercle médian tel que référencé ci-dessus. Il ne nécessite pas de bibliothèque mathématique et est très rapide. (Rendu en environ 500 microsecondes) C'est ce que Windows utilise/utilisé pour pixelliser les cercles.
void DrawCircle(SDL_Renderer * renderer, int32_t centreX, int32_t centreY, int32_t radius)
{
const int32_t diameter = (radius * 2);
int32_t x = (radius - 1);
int32_t y = 0;
int32_t tx = 1;
int32_t ty = 1;
int32_t error = (tx - diameter);
while (x >= y)
{
// Each of the following renders an octant of the circle
SDL_RenderDrawPoint(renderer, centreX + x, centreY - y);
SDL_RenderDrawPoint(renderer, centreX + x, centreY + y);
SDL_RenderDrawPoint(renderer, centreX - x, centreY - y);
SDL_RenderDrawPoint(renderer, centreX - x, centreY + y);
SDL_RenderDrawPoint(renderer, centreX + y, centreY - x);
SDL_RenderDrawPoint(renderer, centreX + y, centreY + x);
SDL_RenderDrawPoint(renderer, centreX - y, centreY - x);
SDL_RenderDrawPoint(renderer, centreX - y, centreY + x);
if (error <= 0)
{
++y;
error += ty;
ty += 2;
}
if (error > 0)
{
--x;
tx += 2;
error += (tx - diameter);
}
}
}
SDL permet aux bibliothèques tierces de dessiner sur une texture. Si le Caire était souhaitable, il pourrait être utilisé dans une fonction comme celle-ci:
cairo_t*cb(cairo_t*cr)
{cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
cairo_rectangle(cr, 10, 20, 128, 128);
cairo_stroke(cr);
return cr;
}
alors cb peut être passé à cette fonction:
cairo_t*cai(SDL_Window*w,SDL_Renderer*r,cairo_t*(*f)(cairo_t*))
{int width, height, pitch;void *pixels;
SDL_GetWindowSize(w, &width, &height);
SDL_Texture*t=SDL_CreateTexture(r,SDL_PIXELFORMAT_ARGB8888,SDL_TEXTUREACCESS_STREAMING,width,height);
SDL_LockTexture(t, NULL, &pixels, &pitch);
cairo_surface_t *cs=cairo_image_surface_create_for_data(pixels,CAIRO_FORMAT_ARGB32,width,height,pitch);
cairo_t*s=cairo_create(cs);
cairo_t*fr=f(s);SDL_UnlockTexture(t);SDL_RenderCopy(r,t,NULL,NULL);SDL_RenderPresent(r);
return fr;
}
Si vous voulez faire un cercle ou une ellipse sans bibliothèques tierces, incluez math.h et utilisez la fonction ci-dessous que j'ai écrite. Il dessinera très bien une ellipse ou des cercles aliasés. Testé sur SDL 2.0.2 et fonctionne. Il dessine un arc de quadrant et reflète les autres arcs, réduisant les appels à cosf et sinf.
//draw one quadrant arc, and mirror the other 4 quadrants
void sdl_ellipse(SDL_Renderer* r, int x0, int y0, int radiusX, int radiusY)
{
float pi = 3.14159265358979323846264338327950288419716939937510;
float pih = pi / 2.0; //half of pi
//drew 28 lines with 4x4 circle with precision of 150 0ms
//drew 132 lines with 25x14 circle with precision of 150 0ms
//drew 152 lines with 100x50 circle with precision of 150 3ms
const int prec = 27; // precision value; value of 1 will draw a diamond, 27 makes pretty smooth circles.
float theta = 0; // angle that will be increased each loop
//starting point
int x = (float)radiusX * cos(theta);//start point
int y = (float)radiusY * sin(theta);//start point
int x1 = x;
int y1 = y;
//repeat until theta >= 90;
float step = pih/(float)prec; // amount to add to theta each time (degrees)
for(theta=step; theta <= pih; theta+=step)//step through only a 90 arc (1 quadrant)
{
//get new point location
x1 = (float)radiusX * cosf(theta) + 0.5; //new point (+.5 is a quick rounding method)
y1 = (float)radiusY * sinf(theta) + 0.5; //new point (+.5 is a quick rounding method)
//draw line from previous point to new point, ONLY if point incremented
if( (x != x1) || (y != y1) )//only draw if coordinate changed
{
SDL_RenderDrawLine(r, x0 + x, y0 - y, x0 + x1, y0 - y1 );//quadrant TR
SDL_RenderDrawLine(r, x0 - x, y0 - y, x0 - x1, y0 - y1 );//quadrant TL
SDL_RenderDrawLine(r, x0 - x, y0 + y, x0 - x1, y0 + y1 );//quadrant BL
SDL_RenderDrawLine(r, x0 + x, y0 + y, x0 + x1, y0 + y1 );//quadrant BR
}
//save previous points
x = x1;//save new previous point
y = y1;//save new previous point
}
//arc did not finish because of rounding, so finish the arc
if(x!=0)
{
x=0;
SDL_RenderDrawLine(r, x0 + x, y0 - y, x0 + x1, y0 - y1 );//quadrant TR
SDL_RenderDrawLine(r, x0 - x, y0 - y, x0 - x1, y0 - y1 );//quadrant TL
SDL_RenderDrawLine(r, x0 - x, y0 + y, x0 - x1, y0 + y1 );//quadrant BL
SDL_RenderDrawLine(r, x0 + x, y0 + y, x0 + x1, y0 + y1 );//quadrant BR
}
}