Hallo,
ich habe eine Skala auf der ich den Verbrauch meiner Beleuchtung
anzeigen will.
Das Problem was ich habe ist den Zeiger zu zeichnen.
mein Mittelpunkt vom Zeiger ist in X84 in Y84,die Zeigerlänge ist
54Pixel.
Bei zb null Watt lcd_line (54,84,84,84).
Wie kann ich jetzt die einzelnen Teilstriche Berechnen.
Vielleicht kann mir einer von ihnen weiterhelfen.
Mfg
Moin,
suche mal nach "Bresenham" - in Wikipedia gibt es unter diesem Begriff
einen Algorithmus, mit dem man Linien zeichnen kann. Den Radius würde
ich in diesem Fall als Tabelle hinterlegen - man kanns aber auch
ausrechnen...
Naja, das Maximum ist ja 100W von der Skala. Bei n Watt Messwert muss
also der Winkel gerade a = 180 * n / 100 sein. Wenn r der Radius von der
Skala in Pixeln ist, dann ist der dazu passende Punkt auf dem Kreis
gerade (r cos(a), r sin(a)) -- unter der Annahme, dass der Startpunkt
des Zeigers (also der Mittelpunkt der Skala) gerade (0, 0) ist, sonst
halt entsprechend verschieben. Wie immer halt bei einem Kreis. ;)
Grüße,
Sven
mike schrieb:> Wenn ich mich nicht irre sind 0Grad=50Watt,> das wäre dann zb. bei 0Watt -180Grad und bei 100Watt 360Grad.
Nicht einmal zwei dieser drei Aussagen passen zusammen, geschweige denn
alle. Zeichne Dir das mal auf.
Du kannst sagen 0 Watt sind -90 Grad, dann sind 50 Watt 0 Grad und 100
Watt sind +90 Grad. Oder Du sagst 0 Watt sind 0 Grad, 50 Watt sind 90
und 100 Watt sind 180. Geht auch.
Deine Lösung sieht ziemlich "over-engineered" aus (funktioniert sie denn
wenigstens?). Du musst doch bloß das ausrechnen was ich gesagt habe. Die
Koordinaten vom Zielpunkt sind (r cos(180 * n / 100) + ofs_x, r sin(180
* n / 100) + ofs_y). Fertig. Eine Zeile.
ich habe das nach ihren Vorschlag umgesetzt leider führt die dann immer
zum Reset.
Könnte ich die werte auch in eine Tabelle eintragen für den Startwert
x,y,
das währen dann 100 Werte.
Müsste ich mir alle einzeln Ausrechnen.
So, ich habe nochmal mit 50 Gerechnet.
Mein Taschenrechner habe ich auf Radisnt umgestellt.
Aber leider passt dass ergebniss nicht
x_end 59.355
y_end 133.169
x_end sollte doch bei 84 bleiben
y_end sollte bei 55 sein
Könnte mir von ihnen mir ein wenig auf die sprünge helfen.
Du musst auch darauf achten, dass in Deiner Skala der Nullpunkt links
liegt, aber bei den trigonometrischen Funtkionen liegt er rechts.
Außerdem kann sein, dass positive x nach rechts zeigen, aber positive
y-Werte nach unten und nicht wie in der Mathe üblich nach oben.
#define PI100 (3.1415926 / 100)
#define XO 84
#define YO 84
minus
|
|
V
x_end = x_mitte - r * cos(PI100 * k);
y_end = y_mitte - r * sin(PI100 * k);
Wenn Du nur Teilstriche haben willst, brauchst Du zwei Radien:
single cosi = cos(PI100 * k);
single sinu = sin(PI100 * k);
x1 = XO - r1 * cosi;
y1 = YO - r1 * sinu;
x2 = XO - r2 * cosi;
y2 = YO - r2 * sinu;
lcd_line(x1, y1, x2 , y2, 1);
Kannst Du auch in eine Zeile schreiben:
lcd_line(XO - r1 * cosi,YO - r1 * sinu,XO - r2 * cosi,YO - r2 * sinu);
eProfi schrieb:
> #define PI100 (3.1415926 / 100)> #define XO 84> #define YO 84>> minus> |> |> V> x_end = x_mitte - r * cos(PI100 * k);> y_end = y_mitte - r * sin(PI100 * k);> Wenn Du nur Teilstriche haben willst, brauchst Du zwei Radien:> single cosi = cos(PI100 * k);> single sinu = sin(PI100 * k);> x1 = XO - r1 * cosi;> y1 = YO - r1 * sinu;> x2 = XO - r2 * cosi;> y2 = YO - r2 * sinu;> lcd_line(x1, y1, x2 , y2, 1);> Kannst Du auch in eine Zeile schreiben:> lcd_line(XO - r1 * cosi,YO - r1 * sinu,XO - r2 * cosi,YO - r2 * sinu);
Vielen Dank hoffentlich bekomm ich das auch hin.
r1,r2 Währe ja mein Radius.
Das was du suchst, ist nichts anderes als die Anwendung der
Trigonometrie in einem rechtwinkeligen Dreieck.
gegeben ein rechtwinkeliges Dreieck mit der Hypothenuse (die längere
Seite) R, wobei R im Winkel Alpha zur X-Achse liegt.
Gefragt sind die Längen der beiden anderen Seiten.
Die eine hat Seitenlänge R*cos(Alpha)
die andere Seite hat die Länge R*sin(Alpha)
D.h. dies sind auch gleichzeitig die Koordinaten des Punktes, an dem
sich die Hypothenuse mit einem Kreis mit Radius R schneidet.
Alles andere sind jetzt nur noch Anpassungen, weil dein Kreis eben
seinen Mittelpunkt nicht bei den Koordinaten 0/0 hat, sondern dazu
verschoben ist. D.h. auf alle Punkte wird noch die Verschiebung dieses
Mittelpunkts mit aufgerechnet.
Und dann hast du natürlich noch den Fall, dass dein 0-Winkel eben nicht
auf der X-Achse nach rechts verläuft, sondern bei dir eben anders liegt.
Auch gibt es noch den Fall, dass die Y-Koordinate nicht nach oben läuft,
so wie in der Mathematik üblich, sondern nach unten. Daraus resultieren
ein paar Koordinaten Umrechnungen, in dem anstelle Addition eine
Subtraktion erfolgt.
Aber das Grundprinzip sind immer noch die Punktkoordinaten, die sich aus
den Seitenlängen im rechtwinkeligen Dreieck durch Anwendung von Sinus
und Cosinus ergeben.
(Und nicht vergessen: Winkel werden in Radianten angegeben und nicht in
Grad. Ein Vollkreis hat 2*PI Radianten, 180° sind daher PI Radianten.)
Brauchst kein sin/cos Funktionen. Leg dir eine Tabelle mit 50 Werten an
(viertel Kreis reicht). Wenn dein Display 100 Werte pro Halbkreis
darstellen kann Respekt (je nach Gaughe Größe). Zu den Werten kommst du
am Besten mit einem Grafikprogramm. ZB einen Eagle Sheet, Raster 1mm (=
Pixelgröße), Halbkreis zeichen,Messpunkt setzen und du hast deine
Koordinaten, wenn du mit der Maus über den gew. Punkt fährst.So kannst
du jede beliebige Grafik vermessen.
Hab gerade damit eine Analoguhr kreiert. Mit den Cos/Sin Funktionen hat
alles zu lange gedauert (Zeiger Überlappungen ect.) und hat riesigen
Code gekostet.
SG Christen
"Hm, jetzt hätte ich die Striche gern ein bisschen länger... Mist,
nochmal alles von vorne machen!"
Dieses Verfahren ist meiner Meinung nach nicht besonders toll... wenn es
unbedingt schnell sein soll, kann man die Werte auch nach dem ersten
Zeichnen in einen Cache schreiben.
Am besten eine, die programmatisch generiert ist ;)
Notfalls auch auf einem (größeren) Rechner.
Python eignet sich hervorragend, um sowas schnell zusammenzuhacken.
ich habe mal noch eine Frage ,
Die Funktion wird aufgerufen wert hat jetz 512,zeiger wird gezeichnet,
soweit geht alles.
nun wird die Funktion ein zweites mal aufgerufen wert hat jetz 130, nun
wollte ich den zeiger vom ersten wert weis neuzeichnen und danach den
zeiger mit dem neuen Wert zeichnen, anstatt jedes mal das BMP file neu
laden.
Leider geht das nicht so wie ichs mir dachte
vielleicht kann mir wer weiterhelfen
Sollte aber gehen wenn leistung_analog_w jedesmal mit identischem xpos
und ypos aufgerufen werden denn xm und xm_alt und ym und ym_alt sind
zufälligerweise gleich.
Bloss: Woher weiss der erste Aufruf von lcd_linie dass sie weiss
zeichnen soll? Der letzte Parameter ist ebenfalls 1, zeichnet die
Funktion im XOR Mode?
mike schrieb:> So gehts wunderbar,
Wenn es einem egal ist, dass man dieselbe Berechnung 2 mal ohne guten
Grund macht, dann: ja
da x_m_alt/y_m_alt sowieso nie andere Werte bekommen als x_m/y_m würde
ich dieses Variablenpärchen gleich mal eliminieren. In Wirklichkeit
braucht die keiner. x_m/y_m alleine tut es auch.
damit bleibt hier
> // kopiere Werte in alt>> x_e_alt = x_m_alt - r * cos(PI100 * wertk);> y_e_alt = y_m_alt - r * sin(PI100 * wertk);
übrig
x_e_alt = x_m - r * cos(PI100 * wertk);
y_e_alt = y_m - r * sin(PI100 * wertk);
und wenn man das mit dem Code 3 Zeilen drüber vergleicht
x_e = x_m - r * cos(PI100 * wertk);
y_e = y_m - r * sin(PI100 * wertk);
dann kommt man drauf: das ist genau das gleiche.
Wozu also neu durch den sin/cos durchjagen?
Ein
x_e_alt = x_e;
y_e_alt = y_e;
tuts auch.
Wenn du Strukturverbesserungen in deinen Code bringen willst, dann denk
darüber nach, dass ja eigentlich x und y immer zusammengehören und eine
logische Einheit, eine 'Koordinate' bilden.
Ergo
Das beispiel von Karl Heinz Buchegger hier zeigt das haut hin,
Nun meine Frage ich wollte nun de Zeiger etwas veränder breiter machen,
ich habe erstmal in y 1pixel dazugerechnet aber das geht ja nur null
Grad und bei 180Grad .
Ich wollte gern das der Zeiger ungefähr so aussieht wie auf dm Bild hier
http://i01.i.aliimg.com/img/pb/622/182/379/379182622_737.jpg
Vielleicht könnte mir einer von ihnen weiterhelfen wie ich das richtig
berechne
Mfg
mike schrieb:> Vielleicht könnte mir einer von ihnen weiterhelfen wie ich das richtig> berechne
Jetzt beginnt der Bereich, in dem Computergraphik wirklich anfängt.
Am sinnvollsten beschäftigt man sich jetzt bereits mit Transformationen.
Keine Angst, so wild ist das im 2D noch nicht.
Wenn ich vormittags über ein wenig Zeit hab, dann bereite ich dir was
vor.
Karl Heinz Buchegger schrieb:> Wenn ich vormittags über ein wenig Zeit hab, dann bereite ich dir was> vor.
Sorry. Ich hatte tagsüber wenig Zeit einen Artikel zu schreiben, der ein
wenig Vorbereitung bedarf. Ich werde hier auch wahrscheinlich mehrere
Postings folgen lassen, weil ich denke, dass es ohne Zeichnungen nicht
gehen wird und ich möchte die Zeichnungen jeweils in einen Zusammenhang
stellen. Ich geb Bescheid, wenn die 'Serie' abgeschlossen ist.
Die gute (oder schlechte) Nachricht zuerst:
Nach reiflicher Überlegung, denke ich, dass es nicht notwendig ist, dich
in die tieferen Geheimnisse von Transformationen einzuweihen. Für deine
Zwecke, kann das recht einfach gehalten werden. Aber ein bisschen Mathe,
im speziellen Trigonometrie, muss sein. Ohne geht es nun mal nicht.
Aber zuerst mal ein bischen Notation um die Sache ins Rollen zu bringen.
Einiges davon wird im Endeffekt nicht gebraucht werden, aber es schadet
nicht, uns erst mal in der Sprache abzustimmen.
Man kann einen beliebigen Punkt um eine bestimmte Distanz verschieben,
indem man einfach zu seinen Koordinaten die Distanzen addiert
1
x' = x + dx
2
y' = y + dy
Diese beiden Gleichung besagen, dass ein Punkt mit den Koordinaten x und
y um eine Distanz dx;dy verschoben wird und man dadurch einen neuen
Punkt mit den Koordinaten x' und y' erhält.
Um die Notation etwas zu vereinfachen, definieren wir einen
Spaltenvektor als so eine Einheit von x und y. Der Vektor P wäre dann
der Punkt
1
| x |
2
P = | | ( die | sind einfach nur senkrechte Striche
3
| y | wie sie in Mathe üblich sind. Ich werde sie
4
in Bälde einfach weglassen )
die Distanz, um die verschoben wird, kann man ebenfalls als Vektor
anschreiben
1
| dx |
2
T = | |
3
| dy |
und das Ergebnis der Translation ist dann der neue Punkt, als Vektor
ausgedrückt also der
1
| x' |
2
P' = | |
3
| y' |
Man kann also die beiden obigen Gleichungen
1
x' = x + dx
2
y' = y + dy
auch als Vektorgleichung aufschreiben:
1
P' = P + T
bis jetzt ist noch nichts aufregendes passiert. Einfach nur im
Hinterkopf halten, dass Grossbuchstaben immer für Vektoren stehen, die
(weil wir uns ja im 2D bewegen) aus jeweils einer x Komponente und einer
y Komponente bestehen. Werden 2 Vektoren addiert, dann werden sie
komponentenweise addiert. Um also P + T zu berechnen, rechnet man P.x
(das steht für die x-Komponente des Vektors P), also P.x + T.x bzw. P.y
+ T.y und das jeweilige Ergebnis geht nach P'.x bzw. P'.y
Ich denke, bis hier her ist das noch nicht weiter schwer. Auch wenn da
jetzt Begriffe wie Vektoren gefallen sind, ist das einfach nur eine
Notation, mehr nicht.
Der springende Punkt ist nun, dass man eine Figur als ganzes verschiebt,
der Translation T unterwirft, indem man die Transformation
1
P' = P + T
einfach auf jeden Punkt der Figur anwendet, siehe Bild.
Da diese Figur aus Linien besteht, genügt es dabei, nur die Endpunkte
der Linien zu transformieren. Eine gerade Linie ist auch nach der
Transformation wieder eine gerade Linie.
Rotationen
Ein einzelner Punkt kann um den Ursprung des Koordinatensystems um den
Winkel a gedreht werden, indem die Transformation
1
x' = x * cos(a) - y * sin(a)
2
y' = x * sin(a) + y * cos(a)
anwendet.
Man kann diese Formeln relativ leicht aus der Trigonometrie am
rechtwinkeligen Dreieck herleiten, ich spars mir aber, da es nicht viel
zur Sache beiträgt. Bei Bedarf ist das aber mit einer Zeichnung schnell
einsichtig, warum das so ist.
Wieder kann man diese Transformation in Vektor/Matrix-form schreiben als
1
| x' | | cos(a) -sin(a) | | x |
2
| | = | | * | |
3
| y' | | sin(a) cos(a) | | y |
oder eben als Vektorgleichung
1
P' = R * P
wobei das * die Matrixmultiplikation darstellt. Also alle die
Komponenten der jeder Zeile der Matrix mit der jeweiligen Komponente des
Vektors multiplizieren und die Summe drüber bilden.
(die erste Zeile der Matrix lautet cos(a) - sin(a) , die erste (und
einzige Spalte) der zweiten Matrix/Vektors lautet x y, daher cos(a)
mal x bzw. -sin(a) mal y; und die Summe der beiden Teilausdrücke ergibt
die erste Komponente des Ergebnisses. Vergleichen mit der Ausgangsformel
zeigt: passt, kommt genau dasselbe raus.
Hört sich schlimmer an als es ist, nach 2 mal selber auf dem Papier
machen, hat man den Dreh raus)
Auch hier gilt wieder:
Um ein Objekt als ganzes zu transformieren, unterwirft man einfach jeden
einzelnen Punkt des Objektes der Transformation und in unserem Falle
genügt es dazu, einfach nur die Endpunkte der Linien zu betrachten
Die zuletzt eingeführte Rotation hat ein kleines 'Problem'. Sie dreht
immer um den Ursprung des Koordinatensystems.
Kann man degegen etwas machen?
Was tun, wenn ich nicht um den 0-Punkt sondern um einen bestimmten Punkt
Q drehen möchte?
Nun ganz einfach.
Mittels einer Transformation, die nichts anderes tut als Q in den
Ursprung des Koordinatensystems zu verschieben, kann man ja den
Drehpunkt in den Ursprung bringen. Danach dreht man um den gewünschten
Winkel und verschiebt das Ergebnis wieder zurück, macht also die
ursprüngliche Verschiebung wieder rückgängig.
Möchte man also um den Punkt/Vektor Q eine Drehung um den Winkel a
ausführen, so berechnet sich der jeweils neue Punkt P' zu
1
P' = R * ( P - Q ) + Q
P - Q verschiebt den Q in den Ursprung und wendet dieselbe
Transformation auf P an.
Die Multiplikation mit R dreht den Punkt rund um den Ursprung
Und die Addition von Q hebt schliesslich die Verschiebung in den
Ursprung wieder auf.
Man kann nun durch weitere mathematische Operationen all die
Einzeloperationen zu einer einzigen Matrixmultiplikation zusammenfassen,
ich denke aber, dass dies in deinem Fall nicht notwendig sein wird. Bei
deinen 3 Operationen kann man die auch ganz gut hintereinander
ausführen.
Soweit so gut.
Wenn du also deinen Zeiger nicht einfach nur als Linie auffasst, sondern
als Polygon, also eine Abfolge von Linien, die zb so aussehen (Bild)
(du brauchst nur die Eckpunkte der Linien)
dann kannst du mit dem bisherigen Rüstzeug diesen Zeiger durch
Kombinationen von Transformationen und Rotationen an jedem beliebigen
Ort und in jeder beliebigen Orientierung zeichnen lassen, einfach nur
indem du entsprechende Verschiebungen bzw. Drehungen miteinander
kombinierst.
Besonders einfach wird die ganze Sache, wenn du deinen Zeiger von vorne
herein gleich mal so ins Koordinatensystem legst (die Koordinaten der
Endpunkte festlegst), dass der gewünschte Drehpunkt des Zeigers von
vorne herein im Koordinatenursprung zu liegen kommt. Wenn nicht, dann
ist das auch kein Beinbruch, du weißt ja jetzt, wie man um jeden
beliebigen Punkt drehen kann.
Hast du dann alle Eckpunkte deiner Zeigerfigur entsprechend
transformiert, dann verbindest du die so transformierten Eckpunkte
wieder durch Linien und lässt sie dir ausgeben.
Das heißt jetzt für dich.
Angenommen du hast deinen Zeiger definiert als
1
structcoord
2
{
3
int16_tx;
4
int16_yy;
5
};
6
7
structcoordZeiger[]=
8
{
9
{-10,0},
10
{0,-5},
11
{55,0},
12
{0,5}
13
};
(sollen die Koordinaten des weiter oben blau gemalten Zeigers sein.)
dann genügt es in deinem Fall, jeden dieser Punkt einfach um den
Ursprung zu drehen
und danach an das von die angedachte Zentrum zu verschieben
1
for(i=0;i<4;i++)
2
{
3
tmp[i].x+=center.x;
4
tmp[i].y+=center.y;
5
}
um damit die Koordinaten der verschobenen und gedrehten Punkte zu
bekommen, so dass du nur noch entsprechende Linien ausgeben musst
1
for(i=0;i<3;i++)
2
{
3
lcd_line(tmp[i].x,tmp[i].y,
4
tmp[i+1].x,tmp[i+1].y);
5
}
6
lcd_line(tmp[3].x,tmp[3].y,tmp[0].x,tmp[0].y);
um damit den Zeiger an der gewünschten Position und in der gewünschten
Orientierung zu sehen. Und wenn du dann den Winkel veränderst, dann
sollte sich eigentlich der Zeiger um seinen Drehpunkt drehen (wenn du
den Ausradier- / Hinmal- Mechanismus noch richtig bedienst).
So, das wars.
Ich denke, das sollte fürs erste ausreichend sein, um dir das unbedingt
notwendig Rüstzeug zu geben, um deine ersten Schritte in die Welt der
Computergrafik zu gehen.
Probier ein bischen rum, lass dich nicht frustrieren, arbeite in kleinen
Schritten, dann kann nicht viel schief gehen.
Von da weg öffnet sich das weite Feld der Computergrafik und man kann da
noch eine Menge anderer Dinge ausprobieren und sich überlegen. Aber fürs
erste braucht es für deine Zwecke nicht mehr als diese einfachen
Konzepte
* ein Polygon wird beschrieben durch eine Abfolge von Punkten
* Transformation
* Rotation
* man kann Transformationen und Rotationen auch hintereinander ausführen
* ein Polygon wird transformiert, indem man seine Eckpunkte durch alle
Transformationen schleust.
@ Karl Heinz Buchegger (kbuchegg) (Moderator)
Schreib doch lieber ein Buch! Oder wenigstens einen Artikel. Denn sonst
ist deine Arbeit an nur einen Fragesteller "verschwendet".
Falk Brunner schrieb:> @ Karl Heinz Buchegger (kbuchegg) (Moderator)>> Schreib doch lieber ein Buch! Oder wenigstens einen Artikel.
Hab ich mir sogar überlegt, ob ich nicht im Wiki einen Artikel dazu
mache. Aber da muss ich dann noch weiter ausholen :-)
Karl Heinz Buchegger schrieb:> Aber da muss ich dann noch weiter ausholen
Deine Zeiger werden wird noch viele Freunde finden, da lohnt sich schon
ein kurzer Artikel mit Verweis auf diese Diskussion.
Hinzuzufügen wäre noch, das bei Druck von Skalen gelegentlich größere
Ungenauigkeiten durch Druckertreiber und mechanische Druckerprobleme
auftreten. Deshalb zur Probe immer erst Quadrat 100x100 mm drucken und
messen!
Karl Heinz Buchegger schrieb:> So, das wars.> Ich denke, das sollte fürs erste ausreichend sein, um dir das unbedingt> notwendig Rüstzeug zu geben, um deine ersten Schritte in die Welt der> Computergrafik zu gehen.
Toll! Aber warum erst jetzt? ;-)
Ich habe mir diese Methoden mühsam im Netz zusammensuchen müssen als ich
mir das Ziffernblatt + Zeiger meiner Scopeuhr
(Beitrag "Re: Zeigt her Eure Kunstwerke !")
programmiert habe.
Ich finde deine Erklärung super und gut verständlich.
Und ich habe es ziemlich genauso gelöst wie du es hier beschrieben hast.
Das freut mich jetzt, ich habe überhaupt keine Ahnung von
Computergrafik. Also hab ich nicht soviel Fehler gemacht. :) Ich hätte
das gerne so als "Kochrezept" irgendwo haben wollen, es war schon etwas
mühsam überall die Schnipsel (Bresenham, Translation, Rotation u.s.w.)
zusammenzusuchen. Na ja, dümmer bin ich so auch nicht geworden. So gibt
es hier jetzt eine prima Erklärung.
Aber da einen Artikel von zu machen, dass wäre schon prima Karl-Heinz.
Du kannst gut erklären. Danke im Nachhinein.
Hallo Karl Heinz Buchegger,
Vielen vielen Dank für diese sehr ausführliche erklärung.
ich habe aber noch ein Problem und zwar beim Compilieren.
Bekomme das nicht Compilliert
Vielleicht können sie mir weiterhelfen
MFG
mike schrieb:> Vielen vielen Dank für diese sehr ausführliche erklärung.> ich habe aber noch ein Problem und zwar beim Compilieren.> Bekomme das nicht Compilliert
Wie äußert sich das?
-> Der Compiler liefert Fehlermeldungen.
Und was sind das für Fehlermeldungen?
-> Undeklarierte Variablen, Funktionen und Datentypen.
Und was tut man dagegen?
-> Tippfehler beseitigen und die entsprechenden Variablen an geeigneter
Stelle deklarieren und die passenden Headerfiles mit den Funktions-
und Typdeklarationen includen.
Ansonsten ist das Programm nämlich korrekt.
So ich bekomme Trotzdem noch eine Fehlermeldung beim compillieren
Fehlermeldung:
error: 'tmp' undeclared (first use in this function)
error: (Each undeclared identifier is reported only once
error: for each function it appears in.)
mike schrieb:> So ich bekomme Trotzdem noch eine Fehlermeldung beim compillieren> Fehlermeldung:> error: 'tmp' undeclared (first use in this function)
Ist das die einzige Meldung?
Hier sollte nämlich auch noch eine ausgegeben werden, weil der
Struct-Name fehlt:
Hi
Yalu X. schrieb:> Ändere diese Zeile mal in> struct coord tmp[4];
Denzeiger zeichnen das geht erstma
So nun sollte aber der alte Zeiger bevor der neue Gezeichnet wird
Überschriben werden aber leider geht das so nicht wie ich mir das dachte
mfg
andreas schrieb:> Hi>> Yalu X. schrieb:>> Ändere diese Zeile mal in>> struct coord tmp[4];> Denzeiger zeichnen das geht erstma>> So nun sollte aber der alte Zeiger bevor der neue Gezeichnet wird> Überschriben werden aber leider geht das so nicht wie ich mir das dachte
Andreas, ich will dir nicht zu nahe treten.
Aber du musst schon erst mal C lernen, sonst wird das nichts.
Wenn du bei deinem Auto selbst das Motoröl wechseln willst, und man dir
erst mal erklären muss, was ein Schraubenschlüssel ist, dann wird dir
jeder SChrauber sagen: Weißt was, lern erst mal ein wenig mit deinem
Werkzeug umzugehen und dann kannst wieder kommen.
Wenn du von deiner Programmierprache noch nicht mal 10% des
Sprachumfangs beherrscht (und selbst das nur so lala), dann hat es
keinen Sinn, wenn wir uns über weitergehende Programmiertechniken
unterhalten. Ich bin sicher kein Unmensch und schreib auch mal für
andere Code, aber er gibt auch eine Grenze an der ich sage: sorry.
Entweder du lernst das, oder du bezahlst mich dafür, dass ich das
gelernt habe. Schliesslich verdiene ich meine Brötchen damit und muss
davon leben. Ich hab nicht Jahre in meine Ausbildung investiert, damit
ich dir hier Dinge beibringe, die du in jedem C-Buch, dass du bei Amazon
um 12 Euro kaufen kannst, nachlesen kannst. Sonst kann ich dir das
nämlich auch gleich fix fertig schreiben - das wäre für mich nämlich
einfacher und geht auch schneller. Wer ein Projekt machen will, muss
sich zuallererst fragen: was müsste ich dazu lernen, wo muss ich mich
weiterbilden.
Leider scheint dieser Gedanke in der heutigen Zeit vielen Menschen immer
mehr absurd vorzukommen, dass man Dinge die man machen will auch lernen
muss.
Du willst eine Programmiersprache anwenden, um ein Problem zu lösen?
Dann lerne die Programmiersprache und wir können uns über deine
Möglichkeiten zur Lösung des Problems unterhalten. Aber wenn ich dir
erst mal jedes 3. Wort erklären muss, dann macht das einfach keinen
Spass. Ich diskutiere nicht mit jemandem darüber, wie man einen
englischsprachigen Roman aufbaut, der gerade mal 3 Brocken Englisch
kann.
Hallo Karl Heinz ,
Ich habe auch mal dein Ausführliches Beispiel mal ausprobiert.
An dieser stelle vielen Dank für die Erklährung.
Ich habe aber ein Problem, Das der Zeiger bei mir Verkehrt herum
Angezeigt wird.
Zeiger hat den Wert Null (siehe Bild Zeiger_1 Wert null) und bei 100
(siehe Bild Zeiger_1 Wert 100%).
Wo hab ich da jetz einen Denkfehler drin
mfg
Robert schrieb:> Wo hab ich da jetz einen Denkfehler drin
ohne Code ist das schwer zu sagen, aber ich denke, du hast nicht
bedacht, dass mathematische Winkel ihren 0-Winkel auf der X-Achse haben
und entgegegen dem Uhrzeigersinn größer werden.
Hallo,
Ich habe mal das Beispiel von Karl-Heinz ausprobiert das Funktioniert
1a.
So nun meine Frage, wie mus ich vorgehen das ich einen gefüllten Zeiger
bekomme.
Da ich noch nicht so bewandert bin in C , gaher meine Frage.
Mfg
Dann muss man sich eine Funktion erstellen, welche eine Fläche (Polygon)
füllen kann und anstatt von Linien zeichnet man Polygone mit den
gleichen Eckpunkten. Für den Anfang nimmt man das einfachste Polygon,
das Dreieck. Dafür einen Füllalgorithmus zu schreiben ist mal ne gute
Aufgabe.
Und wenn man das alles durch hat wird man feststellen, dass der Kram zu
langsam ist. Dann nimmt man fertig gezeichnete Bilder, welche im Flash
liegen, und kopiert sie einfach auf's LCD. Muss man nicht soviel rechnen
und man kann beliebig komplexe Bilder/Animationen darstellen.
Falk Brunner schrieb:> Und wenn man das alles durch hat wird man feststellen, dass der Kram zu> langsam ist. Dann nimmt man fertig gezeichnete Bilder, welche im Flash> liegen, und kopiert sie einfach auf's LCD. Muss man nicht soviel rechnen> und man kann beliebig komplexe Bilder/Animationen darstellen.
Ja aber dann bräuchte ich ja auch 180 Enzelbilder wenn die Teilung zb
1Grad auflösung währ.
Hallo,
So hier ist die Funktion um ein Dreick gefüllt zu Zeichnen.
Wie kann ich das nun mit Karl Heinz Buchegger sein Beispiel verknüpfen,
muss ich denn für jeden Punkt am Dreieck diese Berechnung machen.
zb.
tmp[i].x = Zeiger[i].x * cosAlpha - Zeiger[i].y * sinAlpha;
tmp[i].y = Zeiger[i].x * sinAlpha + Zeiger[i].y * cosAlpha;
fillTriangle(tmp[i].x,tmp[i].y,100,100,150,50, Red);
Könnte mir denn da jemand weiterhelfen.
karl schrieb:> Hallo,>> So hier ist die Funktion um ein Dreick gefüllt zu Zeichnen.> Wie kann ich das nun mit Karl Heinz Buchegger sein Beispiel verknüpfen,> muss ich denn für jeden Punkt am Dreieck diese Berechnung machen.> zb.>>> tmp[i].x = Zeiger[i].x * cosAlpha - Zeiger[i].y * sinAlpha;> tmp[i].y = Zeiger[i].x * sinAlpha + Zeiger[i].y * cosAlpha;>> fillTriangle(tmp[i].x,tmp[i].y,100,100,150,50, Red);>> Könnte mir denn da jemand weiterhelfen.
Ja klar musst du alle Punkte deines Polygons entsprechend drehen.
Und danach ist es ein Flächenfüller, der das Polygon entsprechend
gefüllt in die Pixel malt.
Zu deinem Dreicksfüller:
Es ist reichlich übertrieben, da jetzt einen Bresenham darauf
anzusetzen, die einzelnen Linien für die Füllung hinzumalen.
Es gibt zwar mehrere Verfahren, wie man beliebige Polygone füllen kann,
und das Tracen der Outline ist nicht so ohne, aber die Füllinien sind zb
dergestalt, dass sie immer waagrecht, bzw. senkrecht verlaufen (je nach
Verfahren). D.h. hier lohnt es sich schon wieder, eine Spezialroutine zu
haben, die für diesen Fall (waagrechte bzw. senkrechte Linie) speziell
optimiert ist, so dass man nicht auf den allgemeinen Fall zurückgreifen
muss. Auch ist es je nach Polygon so, dass oftmals mehrere Pixel
nebeneinander zu setzen sind, zum Beispiel 8, was bei einer LCD
Aufteilung von 8 Pixel nebeneinander dazu führt, dass man nicht
einzelpixelweise an die Sache ranngeht, sondern im Bildspeicher ein Byte
komplett auf 'Schwarz' setzt, in dem Wissen, dass man dadurch 8
nebeneinander liegende Pixel auf einmal gesetzt hat. Da steht dir jetzt
Tür und Tor offen für eigene Ideen, was du noch alles optimieren bzw.
vereinfachen kannst, weil du eben spezielle Fälle vorliegen hast, die du
ausnutzen kannst.
Edit:
Bei dir dann wohl waagrechte Linien. Denn Sy und Ey sind in deinem
Scanline Verfahren immer gleich. Ob waagrecht jetzt so schlau ist oder
nicht, kann hier keiner sagen, das hängt zum Beispiel auch von der
Organisation deines Grafik-LCDs ab ob dort die BIts des Bildspeichers
waagrechte oder senkrechte Pixel bevorzugen.
Aber sei es drum. Du hast jetzt einen Dreicksfüller basierend auf einem
Scanline verfahren. Jetzt gilt es das auf allgemeinere Polygone zu
verallgemeinern.
Können schon.
Aber wo ist dann eigentlich deine Leistung?
Installier dir einen C-Compiler auf dem PC und teste und debugge deine
Funktionen dort. Das geht dort wesentlich einfacher. Als Ausgabe machst
du dir ein 2D-Array aus char, welches du danach (oder wenn du es
brauchst auch zwischendurch) ausgibst. Ein '#' stellt ein gesetztes
Pixel dar, ein Leerzeichen ein nicht gesetztes. Du kannst deine
Funktionen mit printf spicken, so viel du willst und so viele wie du
brauchst um nachzuvollziehen, was deine Funktion macht und mit dem zu
vergleichen, wie sie eigentlich machen sollte.
karl schrieb:> noch was vergessen>>> struct coord> {> u16 Ax;> u16 Ay;> u16 Bx;> u16 By;> u16 Cx;> u16 Cy;> };>
Eine 2D-Koordinate, also 1 Punkt, hat bei dir 6(!) Zahlenwerte?
Na bumm.
Da hast du aber so einiges überhaupt nicht verstanden.
Karl Heinz Buchegger schrieb:> karl schrieb:>> noch was vergessen>>>>>> struct coord>> {>> u16 Ax;>> u16 Ay;>> u16 Bx;>> u16 By;>> u16 Cx;>> u16 Cy;>> };>>>> Eine 2D-Koordinate, also 1 Punkt, hat bei dir 6(!) Zahlenwerte?> Na bumm.>> Da hast du aber so einiges überhaupt nicht verstanden.
Das wahr ja von mir auch völliger Quatsch.
ich bekomme das Dreieck mit den Coordinaten die im Struct sind nicht
angezeigt.
Mit dem Ausgeklammerten Werten wirds Angezeigt.
Karl Heinz Buchegger schrieb:> karl schrieb:>> noch was vergessen>>>>>> struct coord>> {>> u16 Ax;>> u16 Ay;>> u16 Bx;>> u16 By;>> u16 Cx;>> u16 Cy;>> };>>>> Eine 2D-Koordinate, also 1 Punkt, hat bei dir 6(!) Zahlenwerte?> Na bumm.>> Da hast du aber so einiges überhaupt nicht verstanden.
Das erklärt auch den Quatsch
ehe dann die 3 transformierten Punkt in den Dreiecksfüller gesteckt
werden. Ok, dem Füller könnte man eine bessere Schnittstelle verpassen,
so dass sie zum Rest des 'Systems' passt(*), aber von abgekupfertem Code
kann man eben nicht alles verlangen. Wenn der Füller erst mal
funktioniert reicht das schon.
1
fillTriangle(tmp[0].x,tmp[0].y,
2
tmp[1].x,tmp[1].y,
3
tmp[2].x,tmp[2].y);
(*) Wozu hat man sich denn sonst eine Struktur für 2D-Koordinaten
eingeführt, wenn man dann erst recht wieder x und y getrennt in die
Funktion reinschiebt. Ein Dreiecksfüller braucht 3 Punkte, die 3
Eckpunkte des Dreiecks. 'Punkte', das ist aber jeweils nichts anderes
als ein 'struct coord'