Erittäin nopea algoritmi ympyrän piirtämiseen ilman trigonometriaa.
Lisää voit lukea täältä:
http://www.funducode.com/freec/graphics/graphics2.htm
Muista linkata mukaan SDL.lib ja SDLMain.lib.
#include <stdlib.h> #include "SDL.h" enum { SCREENWIDTH = 640, SCREENHEIGHT = 480, SCREENBPP = 32, SCREENFLAGS = SDL_ANYFORMAT }; void DrawScene(SDL_Surface* surface) { if ( SDL_MUSTLOCK(surface) ) { if ( SDL_LockSurface(surface) < 0 ) { fprintf(stderr, "Can't lock the screen: %s\n", SDL_GetError()); return; } } int x = 200; // koordinaatit int y = 200; int r = 100; // säde int x1 = 0; // sisäisiä koordinaatteja int y1 = r; int pe = 3 - 2 * r; Uint8 *p = (Uint8 *)surface->pixels; while (x1 < y1) { // piirrä segmentti *(Uint32 *)(p + (y + y1) * surface->pitch + ((x + x1) << 2)) = 255; *(Uint32 *)(p + (y + y1) * surface->pitch + ((x - x1) << 2)) = 255; *(Uint32 *)(p + (y - y1) * surface->pitch + ((x + x1) << 2)) = 255; *(Uint32 *)(p + (y - y1) * surface->pitch + ((x - x1) << 2)) = 255; *(Uint32 *)(p + (y + x1) * surface->pitch + ((x + y1) << 2)) = 255; *(Uint32 *)(p + (y - x1) * surface->pitch + ((x + y1) << 2)) = 255; *(Uint32 *)(p + (y + x1) * surface->pitch + ((x - y1) << 2)) = 255; *(Uint32 *)(p + (y - x1) * surface->pitch + ((x - y1) << 2)) = 255; // korjaa sijaintia if (pe < 0) pe += 4 * x1 + 6; else { pe += 4 * (x1 - y1) + 10; y1 -= 1; } x1 += 1; } if (x1 == y1) { *(Uint32 *)(p + (y + y1) * surface->pitch + ((x + x1) << 2)) = 255; *(Uint32 *)(p + (y + y1) * surface->pitch + ((x - x1) << 2)) = 255; *(Uint32 *)(p + (y - y1) * surface->pitch + ((x + x1) << 2)) = 255; *(Uint32 *)(p + (y - y1) * surface->pitch + ((x - x1) << 2)) = 255; *(Uint32 *)(p + (y + x1) * surface->pitch + ((x + y1) << 2)) = 255; *(Uint32 *)(p + (y + x1) * surface->pitch + ((x - y1) << 2)) = 255; *(Uint32 *)(p + (y - x1) * surface->pitch + ((x + y1) << 2)) = 255; *(Uint32 *)(p + (y - x1) * surface->pitch + ((x - y1) << 2)) = 255; } // poistetaan lukitus if ( SDL_MUSTLOCK(surface) ) { SDL_UnlockSurface(surface); } //päivitä pinta SDL_UpdateRect(surface, 0, 0, 0, 0); } int main(int argc, char* argv[]) { //Alusta SDL SDL_Init(SDL_INIT_VIDEO); //Aseta exit funktio atexit(SDL_Quit); //luo ikkuna SDL_Surface* pSurface = SDL_SetVideoMode ( SCREENWIDTH, SCREENHEIGHT, SCREENBPP, SCREENFLAGS ); SDL_Event event; for (;;) { if ( SDL_PollEvent ( &event ) ) { if ( event.type == SDL_QUIT ) break; } DrawScene(pSurface); } SDL_FreeSurface(pSurface); return(0); }
MISSÄS Se NELIöJUUri on ;DDdd
Voit sen kotitehtävänä itse lisätä sopivaan kohtaan. ;)
Jep, tuo on hyvä ja yksinkertainen algoritmi ilman mitään raskaita laskutoimituksia. On ollut itselläni jo jonkin aikaa käytössä.
Mutta onkos kukaan sattunut löytämään mitään samanlaista tapaa missä tahansa asennossa olevan ellipsin piirtämiseen? Siihenkin kait lienee olemassa jonkinnäköinen bresenham-algoritmi (tai sitten ei), mutta enpä ole sellaista mistään löytänyt.
if (pe < 0) pe += 4 * x1 + 6; // näitä lukuja muuttamalla saa algoritmin käyrää muutettua else { pe += 4 * (x1 - y1) + 10; // näitä lukuja muuttamalla saa algoritmin käyrää muutettua y1 -= 1; }
Pienillä muutoksilla sain esimerkiksi aikaan pyöristetyn neliön. Tosin pyöristyksen kulmaa ei voi muokata.
tn: Jos ellipsiä muistuttavalle käyrälle on olemassa funktio, voidaan siitä johtaa bresenham-algoritmi soveltamalla linkin osoittamia keinoja.
Edit: Sori, en sitten lukenutkaan viestiäsi riittävän tarkasti :)
Missä tahansa kulmassa oleva ellipsi vaatii varmasti trigonometriaa sisältävän funktion, koska silloinhan täytyy funktion, josta bresenham johdetaan, sisältää kulma muutettuna koordinaateiksi.
Saattaa tulla jopa nopeammaksi käyttää avattua 2x2 matriisia pyöritykseen, sillä silloin pyöritykseen tarvitaan 4 rigonometristä laskutoimitusta.
Kaavan johtaminen vie todennäköisesti enemmän tehoa, mutta tietenkään ei voi olla varma ennen kuin on kokeillut.
Pitäisikö tuon piirtää oikea ympyrä vai ellipsi? (Ps. Huono shotti, en tiedä miksi mutta jotenkin Gimp bugasi)
Koodi ainakin mukavan nopeanoloista.
Sininen ympyrä siitä pitäisi tulla ainakin Windowsissa.
Ehkä tuo bittisyvyys vaikuttaa asiaan? Tuo minun koodini nimittäin olettaa, että taustapuskuri on 4 bytes/pixel ( << 2).
Asetuksessa tosin säädetään bittisyvyydeksi 32 bittiä, joten tiedähäntä.
Värit johtunevat siitä gimpin bugauksesta?
Algoritmissa vikaa ei pitäisi olla.
Käänsin tuon PHP:lle, ja huomasin että tuossa on saman pikselin piirto kahteen kertaan:
*(Uint32 *)(p + (y + y1) * surface->pitch + ((x + x1) << 2)) = 255; *(Uint32 *)(p + (y + y1) * surface->pitch + ((x - x1) << 2)) = 255; *(Uint32 *)(p + (y - y1) * surface->pitch + ((x + x1) << 2)) = 255; *(Uint32 *)(p + (y - y1) * surface->pitch + ((x - x1) << 2)) = 255; *(Uint32 *)(p + (y + x1) * surface->pitch + ((x + y1) << 2)) = 255; tämä -> *(Uint32 *)(p + (y + x1) * surface->pitch + ((x - y1) << 2)) = 255; *(Uint32 *)(p + (y - x1) * surface->pitch + ((x + y1) << 2)) = 255; tämä -> *(Uint32 *)(p + (y + x1) * surface->pitch + ((x - y1) << 2)) = 255; *(Uint32 *)(p + (y - x1) * surface->pitch + ((x - y1) << 2)) = 255;
Virhe korjattu. Kiitoksia T.M. :)
SIinä tuleee ympy rää jos toistakin ;:PO;PO
Tässä on näitä klassisia SDL-mokia eli virheellinen näyttöpinnan vapautus ja SDL_PollEvent-funktion väärinkäyttö. Turha sitä samaa kuvaa on myöskään jatkuvasti piirtää uudestaan.
Aihe on jo aika vanha, joten et voi enää vastata siihen.