www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Darstellung kreis oder kurve auf GLCD


Autor: HerrmannA (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Habe so ein tolles Dipslay von Display 3000 mit Atmel 128
und möchte einen Kreis darstellen oder Kurven.

Ich habe einen Befehl der einzelne Pixel setzt an Xund Y Pos.

Wie kann man die einzelen pixel für einen Kreis berechnen???

Vielen Dank

Autor: bla (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Viertelkreis:

y = sqrt(r^2 - x^2) und den Rest spiegeln.

Autor: D. W. (dave) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nach "Bresenham Algorithmus" suchen...

Autor: Christoph Kessler (db1uq) (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
ich habs zwar schonmal gepostet, aber hier ist mein Bresenham-Kreis in
AVR-Assembler

Autor: Lehrer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du einen Pixel setzen kannst, und Du in der Schule (6 Klasse ?)
aufgepasst hast, dann solltest Du auch einen Kreis ausgeben können!

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bresenham lernt man nicht in der Schule, sondern im Internet
Aber die Berechnungen sind einfache Additionen und Schiebeoperationen,
das ist wirklich nicht schwer, Herr Lehrer

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe bei Bresenham immer ein Verständnisproblem: Wie kann ich
Kreissegmente (effizient) realisieren, die nicht aus den Achtelkreisen
bestehen (z.B. Kreisbogen von "2 Uhr" nach "1 Uhr")?

Autor: Christoph Kessler (db1uq) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das habe ich auch tunlichst vermieden, meine Routine zeichnet nur ganze
Achtel.

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich habe bei Bresenham immer ein Verständnisproblem: Wie kann ich
> Kreissegmente (effizient) realisieren, die nicht aus den
> Achtelkreisen bestehen (z.B. Kreisbogen von "2 Uhr" nach "1
Uhr")?

Das würde mich auch interessieren.
Weiss jemand, ob es dazu so etwas "einfaches" wie den Bresenham
gibt?
Und wenn wir schon dabei sind, was ist mit Ellipsen, usw.?

Ralf

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich will nicht unbedingt etwas Zeichnen, sondern etwas fräsen...
Hab mich aber noch nicht weiter mit entsprechenden CNC-Seiten
auseinandergesetzt.

Eigentlich müsste man für den entsprechenden Radius die Punkte in ein
Feld schreiben (was natürlich recht groß werden kann), dann die dem
Kreissegment entsprecheden Punkte aus den Teilkreisen
"zusammenbasteln".
Das Feld würde natürlich mit dem Radius wachsen.

Autor: Lehrer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Christoph Kessler
In der ursprünglichen Frage war nicht die Rede von einer schnellen
Routine, sondern generell, wie zeichne ich einen Kreis, wenn ich eine
Funktion zum Setzen von Pixeln habe.

Wenn einer schon mal was von Kreisradius, Sinus und Cosinus (6 Klasse?)
gehört hat, dann sollte er wissen wie es geht - auch für CNC oder
Plotter Anwendungen...

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Fräsplotter arbeiten, soweit ich weiß, immer noch mit dem guten
alten HPGL, da gibts einen Kreisbogenbefehl. Das ist üblicherweise aus
Geradenstücken angenähert. Den Bresenham müßte man vermutlich auf einem
45Grad-Segmentpunkt starten, aber das erste Stück weglassen, bis ein
Schwellwert überschritten ist - den müßte man aber erst mal berechnen.

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine Alternative zu Bresenham ist der CORDIC-Algorithmus, mit dem kann
man Sinus und Cosinus berechnen, dann kann Herr Lehrer auch eine
Kreisgleichung benutzen, ohne Hochsprache.

Autor: Laeubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder Tabellen für Sin/Cos ;)

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Lehrer: Den Schüler will ich sehen, der in der 6.Klasse schon mit Sinus
und Cosinus "rummacht".
Trogometrie ist wohl eher Stoff ab der 8./9. Klasse (Gymnasium).
In der 6. Klasse kommen so nette Sachen wie Wurzelrechnung, gemischte
Brüche (oder wie die heissen) dran.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Lehrer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe mal meine alten Schulbücher angeschaut.
Winkelfunktionen wurden damals in der 7 Klasse Realschule (1980, Baden-
Württemberg) abgearbeitet.

Ich wundere mich, dass die "Nordstaaten" heute überhaupt noch solche
komplexe Sachverhalte im Lehrplan haben... ;-)

Autor: Philipp Karbach (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void rasterCircle(int x0, int y0, int radius)
 {
   int f = 1 - radius;
   int ddF_x = 0;
   int ddF_y = -2 * radius;
   int x = 0;
   int y = radius;

   setPixel(x0, y0 + radius);
   setPixel(x0, y0 - radius);
   setPixel(x0 + radius, y0);
   setPixel(x0 - radius, y0);

   while(x < y)
   {
     if(f >= 0)
     {
       y--;
       ddF_y += 2;
       f += ddF_y;
     }
     x++;
     ddF_x += 2;
     f += ddF_x + 1;

     setPixel(x0 + x, y0 + y);
     setPixel(x0 - x, y0 + y);
     setPixel(x0 + x, y0 - y);
     setPixel(x0 - x, y0 - y);
     setPixel(x0 + y, y0 + x);
     setPixel(x0 - y, y0 + x);
     setPixel(x0 + y, y0 - x);
     setPixel(x0 - y, y0 - x);
   }
 }

hier nochmal die funktion in C. Aus wikipedia ;). getestet,
funktioniert exzellent. viel spaß beim kreisemalen!

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Funktion mal aber nur Vollkreise. Mal damit mal einen, der keine
kompletten Kreissegmente malt.

Autor: Atomica (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab den Algorithmus auch gefunden, aber diese Routine zeichnet ja nur 
den Kreisumfang.

Wir haben gerade ein Projekt an der Hochschule, wo wir Vollkreise 
(Fläche ausgemahlt) auf einem Grafikdisplay anzeigen wollen. Kann mir 
zufällig jemand einen C-Code empfehlen, wodurch man das realisieren 
könnte. Wäre super, wenn jemand antworten würde, sind grad total am 
Verzweifeln.

Danke Im Vorraus

Autor: l00k (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im einfachsten Fall von jedem Punkt des Umfangs eine Linie zum 
Mittelpunkt zeichnen. Sicherlich verbesserungswürdig... ;-)

Autor: Atomica (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gute Idee :-).

Wenn ich den Quellcode, den  Philipp Karbach gepostet habe, und einfach 
am Schluss den Radius dekrementiere (Radius--), und den neue Radius der 
Funktion nochmal übergeben in ner Schleife, bis der Radius 0 ist, würde 
das auch gehen?

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt natürlich viele Möglichkeiten, den Kreislinienalgorithmus
zum Kreisscheibenalgorithmus aufzupimpen. Hier ist die in meinen Augen
fast optimale Variante. Zusätzlich zur Berechnung der Randpunkte eines
Achtelkreises müssen vertikale Linien gezeichnet werden, die zusammen
die Kreisfläche bilden:
void vline(int x, int y1, int y2) {
  int y;

  for(y=y1; y<=y2; y++)
    setPixel(x, y);
}

void rasterDisk(int x0, int y0, int radius) {
  int f = 1 - radius;
  int ddF_x = 0;
  int ddF_y = -2 * radius;
  int x = 0;
  int y = radius;

  vline(x0, y0-radius, y0+radius);

  while(x < y) {
    if(f >= 0) {
      vline(x0+y, y0-x, y0+x);
      vline(x0-y, y0-x, y0+x);

      y--;
      ddF_y += 2;
      f += ddF_y;
    }
    x++;
    ddF_x += 2;
    f += ddF_x + 1;

    vline(x0+x, y0-y, y0+y);
    vline(x0-x, y0-y, y0+y);
  }
}

Das Implementierungsbeispiel für vline() kann für LCDs optimiert
werden, da dort typischerweise bis zu 8 Pixel mit einem Zugriff
gesetzt werden können.

Der Algorithmus zeichnet - abhängig vom Radius - oft zwei der
vertikalen Linien doppelt. Das macht ihn nicht wirklich schlecht, aber
es ist unschön. Auch der Kreislinienalgorithmus hat diese Schwäche,
nur fällt sie dort nicht so arg ins Gewicht, da dort nur ein paar (4
oder 8) Pixel doppelt gezeichnet werden. Beides kann man verbessern,
doch habe ich im Moment keinen Kopf dazu ;-)

Autor: Atomica (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die schnelle Hilfe. Würde das auch funktionieren?
 void rasterCircle(int x0, int y0, int radius)
  {                                        //Beginn Funktion
    while(radius > 0)
    {                                      //Beginn While-Schleife 1
      int f = 1 - radius;
      int ddF_x = 0;
      int ddF_y = -2 * radius;
      int x = 0;
      int y = radius;
 
      setPixel(x0, y0 + radius);
      setPixel(x0, y0 - radius);
      setPixel(x0 + radius, y0);
      setPixel(x0 - radius, y0);
 
      while(x < y) 
      {                                     //Beginn While-schleife 2
        if(f >= 0) 
        {                                   //Beginn If-Schleife
          y--;
          ddF_y += 2;
          f += ddF_y;
        }                                   //Ende If-Schleife                              
        x++;
        ddF_x += 2;
        f += ddF_x + 1;
 
        setPixel(x0 + x, y0 + y);
        setPixel(x0 - x, y0 + y);
        setPixel(x0 + x, y0 - y);
        setPixel(x0 - x, y0 - y);
        setPixel(x0 + y, y0 + x);
        setPixel(x0 - y, y0 + x);
        setPixel(x0 + y, y0 - x);
        setPixel(x0 - y, y0 - x);
      }                                      //Ende While-Schleife 2
      radius--;
      rasterCircle(x0,y0,radius);
    }                                        //Ende While-Schleife 1
  }           

Autor: Atomica (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Damit er den Umfang zeichnet + Vertikallinien müsste der Code dann 
folgendermaßen aussehen oder?
void vline(int x, int y1, int y2) {
  int y;

  for(y=y1; y<=y2; y++)
    setPixel(x, y);
}



void rasterCircle(int x0, int y0, int radius)
  {
    int f = 1 - radius;
    int ddF_x = 0;
    int ddF_y = -2 * radius;
    int x = 0;
    int y = radius;
 
    setPixel(x0, y0 + radius);
    setPixel(x0, y0 - radius);
    setPixel(x0 + radius, y0);
    setPixel(x0 - radius, y0);

    vline(x0, y0-radius, y0+radius);
 
    while(x < y) 
    {
      if(f >= 0) 
      {
        vline(x0+y, y0-x, y0+x);
        vline(x0-y, y0-x, y0+x);
        y--;
        ddF_y += 2;
        f += ddF_y;
      }
      x++;
      ddF_x += 2;
      f += ddF_x + 1;
 
      setPixel(x0 + x, y0 + y);
      setPixel(x0 - x, y0 + y);
      setPixel(x0 + x, y0 - y);
      setPixel(x0 - x, y0 - y);
      setPixel(x0 + y, y0 + x);
      setPixel(x0 - y, y0 + x);
      setPixel(x0 + y, y0 - x);
      setPixel(x0 - y, y0 - x);

      vline(x0+x, y0-y, y0+y);
      vline(x0-x, y0-y, y0+y);
    }
  }


Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es dürfte relativ sinnfrei sein, zuerst die Randpixel zu
malen, wenn dann sowieso eine Linie zu/von diesem Randpixel
geht.

Du solltest dir erst mal die Theorie zu Bresenham reinziehen.
Zuerst der Linen - Bresenham (um mit dem grundsätzlichen Verfahren
warm zu werden) und dann mit der Variation die auf Kreise
losgelassen wird.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Danke für die schnelle Hilfe. Würde das auch funktionieren?

Der Aufruf von rasterCircle am Ende der While-Schleife scheint doppelt
gemoppelt. Außerdem kann ich mir vorstellen (hab's nicht ausprobiert),
dass die Kreisfläche mit dem Verfahren nicht vollständig gefüllt wird,
da in den Regionen, wo die Linie schräg verläuft, der Pixelabstand > 1
ist. Dadurch könnte die Fläche im Bereich der beiden 45°-Achsen Löcher
aufweisen. Aber probier's doch einfach mal aus.

Außerdem wird für jedes gesetzte Pixel deutlich mehr gerechnet als für
das Zeichnen von vertikalen Linien.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.