bildverarbeitung - kreis zeichnen
-
hi,
warum zeichnet mein algo den kreis an der x-achse nicht korrekt?
image: http://oi61.tinypic.com/11lscvl.jpgvoid draw_circle(Mat &src, int x, int y, int r, int value) { for(int x_inc = 0; x_inc <= r; x_inc++) { int y_inc = static_cast<int>((sqrt(static_cast<double>(pow(r, 2) - pow(x_inc, 2))))); set_pixel(src, x + x_inc, y - y_inc, value); set_pixel(src, x + x_inc, y + y_inc, value); set_pixel(src, x - x_inc, y + y_inc, value); set_pixel(src, x - x_inc, y - y_inc, value); }
-
weil das so nicht geht.
iteriere über alle pixel und prüfe ob die distanz zur mitte in einem bestimmten bereich ist.
effizienter wäre es wenn du die koordinaten in einem bestimmten intervall berechnest und da einen punkt zeichnest.
-
Schau dir mal Bresenham-Algorithmus#Kreisvariante_des_Algorithmus an.
-
warum zeichnet mein algo den kreis an der x-achse nicht korrekt?
Weil man fuer ein x mehrere y's manchmal zeichnen muss. Genauso zeichnest du ja auch in der Naehe der y-Achse mehrere x mit gleichem y.
-
Falls dir die beiden guten hier genannten Lösungen für das von knivil erklärte Problem nicht gefallen, kannst du ja einfach nochmal drüberpinseln; aber dieses mal über y iterieren statt über x.
-
knivil schrieb:
warum zeichnet mein algo den kreis an der x-achse nicht korrekt?
Weil man fuer ein x mehrere y's manchmal zeichnen muss. Genauso zeichnest du ja auch in der Naehe der y-Achse mehrere x mit gleichem y.
was meinst du?
-
knivil schrieb:
warum zeichnet mein algo den kreis an der x-achse nicht korrekt?
Weil man fuer ein x mehrere y's manchmal zeichnen muss. Genauso zeichnest du ja auch in der Naehe der y-Achse mehrere x mit gleichem y.
was meinst du?
-
Rechne mal das y_inc für
x_inc=r und für x_inc=r-1
sowie für
x_inc=0 und für x_inc=1 aus.
-
wenn ich mich nicht verrechnet habe, hier das y_inc:
x_inc = r -> y_inc = 0
x_inc = r-1 -> y_inc = -2r - 1x_inc = 0 -> y_inc = r^2
x_inc = 1 -> y_inc = r^2 - 1
-
Du hast die Wurzel vergessen.
Und bedenke auch, dass das alles int sind.Und setz für r ruhig mal einen Wert ein. Nicht zu klein.
(Du kannst auch die Punkte für x_inc=r-2 und x_inc=2, da bei 0 und r Extremwerte sind, die durch das casten nach int besonders hervortreten)
-
#include <cmath> using namespace std; int get_xinc(int r, int y_inc) { return static_cast<int>((sqrt(static_cast<double>(pow(r, 2) - pow(y_inc, 2))))); } int main() { // your code goes here for(int y_inc = 0; y_inc <= 20; y_inc++) { cout << "x_inc: " << get_xinc(20, y_inc) << endl; } return 0; }
hier die ausgabe wenn r = 20 ist, warum gibt diesen sprung von ~10 auf 0?
x_inc: 20 x_inc: 19 x_inc: 19 x_inc: 19 x_inc: 19 x_inc: 19 x_inc: 19 x_inc: 18 x_inc: 18 x_inc: 17 x_inc: 17 x_inc: 16 x_inc: 16 x_inc: 15 x_inc: 14 x_inc: 13 x_inc: 12 x_inc: 10 x_inc: 8 x_inc: 6
-
int get_xinc(int r, int y_inc) { return static_cast<int>((sqrt(static_cast<double>(pow(r, 2) - pow(y_inc, 2))))); }
Boah nö.
int get_xinc(int r, int y) { return std::sqrt( r*r - y*y ); }
-
suarez schrieb:
hier die ausgabe wenn r = 20 ist, warum gibt diesen sprung von ~10 auf 0?
Weil die Steigung zwischen den Punkten gegen Unendlich geht. (Die Tangente im Schnittpunkt mit der X-Achse verläuft senkrecht)
Zeichne es dir auf. Auf Papier, mit Stift.
Wenn du kariertes Papier nimmst, brauchst du noch nicht einmal ein Lineal.
Und wenn der Koordinatenursprung mitten in einem Kästchen ist, dann kannst du die sogar ausmalen.Eine Lösung wäre, dass du mehr Symetrieachse ausnutzt. Im Augenblick werden nur um die X- und Y-Achse gespiegelt. Man kann auch noch um die Diagonalen spiegeln.
set_pixel(src, x + y_inc, y + x_inc, value); // beachte x mit y_inc und umgekehrt // noch die anderen Variation mit +- -+ --
Dann kann die Schleife auch früher abbrechen.
Aber man sollte gleich einen besseren Algorithmus nehmen: http://de.wikipedia.org/wiki/Bresenham-Algorithmus
Da wird das alles beschrieben.
-
ob ich nun die schleife ueber y_inc oder x_inc mache ist egal?
for(int y_inc = 0; y_inc <= r; y_inc++)
-
Hier mal meine Kreisfunktion in der Java-Variante.
public void drawCircle(int x1, int y1, int radius) { int f = 1 - radius; int ddF_x = 0; int ddF_y = -2 * radius; int x = 0; int y = radius; drawPixel(x1, y1 + radius); drawPixel(x1, y1 - radius); drawPixel(x1 + radius, y1); drawPixel(x1 - radius, y1); while (x < y) { if (f >= 0) { --y; ++ddF_y; ++ddF_y; f += ddF_y; } ++x; ++ddF_x; ++ddF_x; f += ddF_x + 1; drawPixel(x1 + x, y1 + y); drawPixel(x1 - x, y1 + y); drawPixel(x1 + x, y1 - y); drawPixel(x1 - x, y1 - y); drawPixel(x1 + y, y1 + x); drawPixel(x1 - y, y1 + x); drawPixel(x1 + y, y1 - x); drawPixel(x1 - y, y1 - x); } }
-
@OberProfi:
ob ich nun x von 0 bis r inkrementiere und y berechne
oder
ob ich nun y von 0 bis r inkrementiere und x berechne bleibt mir ueberlassen?
-
Du läufst ja nie ganz bis zum Radius nur solange bis die Diagonale erreicht ist (x == Y). Der Rest ist reine Spiegelung, die die Symmetrie des Kreises ausnutzt. Das kann du bestimmt auch umbauen und bei y anfangen. Ließ dir einfach mal den BresenhamAlgo dazu durch für mehr Details, bei mir ist das schon lange her.