![]() |
Canvas - gleichschenkliches gefülltes Dreieck
Liste der Anhänge anzeigen (Anzahl: 1)
Ich zeichne auf einen Canvas ein Dreieck.
Delphi-Quellcode:
Das Dreieck ist aber nicht symmetrisch.
procedure TTest.PaintBackground(aGui: TsoGui; aBitmap: TBitmap;
aRect: TRect); const Size = 5; var A: TPoint; B: TPoint; C: TPoint; X, Y, S: Integer; begin ... aBitmap.Canvas.Brush.Color := clGray; aBitmap.Canvas.Pen.Color := clBlack; X := aRect.Left + (aRect.Width div 2); Y := aRect.Top + (aRect.Height div 2); S := (Size div 2); ... A := Point(X - S, Y - S); B := Point(X + S, Y - S); C := Point(X, Y + S); ... aBitmap.Canvas.Polygon([A, B, C]); end; Zuerst lege ich einen Mittelpunkt fest und dann die Entfernung um den Mittelpunkt. Es wird von LinksOben nach RechtsOben, dann nach UntenMitte gezogen und dann zurück nach LinksOben. Nach meinem Verständnis sollte das Dreieck damit symmetrisch aussehen, was es aber nicht ist. Muss man das irgendwie anders lösen? |
AW: Canvas - gleichschenkliches gefülltes Dreieck
kann es sein, dass du Rundungsfehler hast?
bei
Delphi-Quellcode:
würde normalerweis 2,5 rauskommen, was aber nicht in einen Integer passt.
const
Size = 5; X, Y, S: Integer; begin ... S := (Size div 2); ... end; Vielleicht hilft es, wenn du die Berechnungen mit Floats machst und dann auf Integer rundest für die Canvas-Befehle |
AW: Canvas - gleichschenkliches gefülltes Dreieck
"Div" rundet direkt ab. Es kommt also 2 raus.
Vom Mittelpunkt aus gesehen hat das Dreieck jeweils einen Abstand von 2 Pixel. Das sollte also so passen. Das Problem liegt wohl bei der unterschiedlichen Rundung der Windows-API bei den einzelnen Linien. Ich schätze mal dass man damit leben muss oder sonst die Linien einzeln berechnen muss. Aber vielleicht weiß ja jemand noch etwas... |
AW: Canvas - gleichschenkliches gefülltes Dreieck
mmh - ich hab das grad nachgestellt
es scheint wirklich ein Zeichnenproblem zu sein. von C nach B scheint es um ein Pixel zu weit links zu sein |
AW: Canvas - gleichschenkliches gefülltes Dreieck
Du kannst eine diagonale Linie nicht mit gleichviel Pixeln abbilden wie ein horizontale oder eine vertikale Linie. Machst du dein Dreieck größer, wird dieser Eindruck verwischt. Bei vier Pixeln Grundfläche gibt es keinen echten Mittelpunkt mehr für die Spitze des Dreiecks. |
AW: Canvas - gleichschenkliches gefülltes Dreieck
Ja das ist schon richtig.
Man könnte aber die rechte Linie genau so runden wie die linke (also spiegeln). Natürlich weiß die Polygon-Funktion nicht, dass man das als Betrachter als sinnvoll erachten würde. Vielleicht wird eine Linie links+unten nach rechts+oben auch generell anders auf- und abgerundet als in der anderen Richtung. Also ich kann akzeptieren wenn man sagt, "die Standard-Polygon-Funktion kann diesen Sonderfall nicht explizit behandeln", auch wenn das zu einem besseren Ergebnis führen würde. So wird es wohl liegen... |
AW: Canvas - gleichschenkliches gefülltes Dreieck
Du kannst ja mal
![]() |
AW: Canvas - gleichschenkliches gefülltes Dreieck
Bei LineTo fehlt ja auch das letzte Pixel, aber ich hätte gedacht, daß somit nur beim letzen Punkt einer PolyLine das selbe Problem auftritt und es sich bei einem Polygon aufhebt, da dort der letzte Punkt eh dort ist, wo sich schon der erste Punkt hingemalt hatte. :gruebel:
|
AW: Canvas - gleichschenkliches gefülltes Dreieck
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo, dein Dreieck ist vollkommen korrekt, auch wenn es nicht so aussieht.
Wenn man sich nur mal die Endpunkte noch mit einzeichnet, dann fällt es bestimmt besser auf, daß es wirklich stimmt.
Delphi-Quellcode:
Die Zeichenfunktion der rechten Linie ist natürlich andersrum. (von oben nach unten ... von unten nach oben)
procedure TForm5.FormPaint(Sender: TObject);
var X, Y, S, I, J, K: Integer; A: array[0..2] of TPoint; begin X := 20; Y := 20; S := 3; A[0] := Point(X - S, Y - S); A[1] := Point(X + S, Y - S); A[2] := Point(X, Y + S {+ 1}); for I := Low(A) to High(A) do for J := -1 to +1 do for K := -1 to +1 do Canvas.Pixels[A[I].X + J, A[I].Y + K] := clRed; Canvas.Pen.Color := clBlue; Canvas.Polygon(A); end; Links von oben aus jeweils Zwei runter und dann Eines nach rechts. Und Rechts jeweils Zwei nach oben und Eines nach rechts. Passt also ganz genau dazu, wie du es auch zeichnen wolltest. :angle: Bei einer geraden Anzahl (siehe Auskommentiertes) passt es wohl besser zusammen, für diesen Fall der 2:1-Steigung = 2x. |
AW: Canvas - gleichschenkliches gefülltes Dreieck
@stahli
Zu dem Problem. Das liegt in dem Verständnis was eine Canvas-Linie ist. Um die zu verstehen muss man ein Schritt zurück treten. Denkt man nicht darüber nach was eine Canvas-Linie eigentlich ist, denkt man vorschnell, dass es eine mit einem 1-Pixel gezeichnete Linie ist, von Punkt A nach Punkt B. Ist sie aber nicht. Im Grunde ist es eine mit einem Pinsel der Stärke x-Pixel gezeichnete Linie. Und Pinsel der Breite x ist immer in der Form berechnet. Intern mit Nachkommastellen. Guck was Perlsau oben über den Kreis geschrieben hat. Jeder Pixel ist im Grunde ein berechneter Kreis. Der kleinste Kreis ist ein Pixel breit. Er sieht quadratisch aus, ist aber ein berechneter Kreis. D. h. am Anfang und Ende eine Linie, selbst wenn sie ein Pixel breit ist, ist ein Halbkreis. Ist der Pinsel 1-Pixel breit, sieht der Halbkreis wie ein Quadrat aus, ist aber ein Halbkreis. Und nun muss man einen Schritt zurück treten und sich angucken was das alles ist. So rechteckig das für uns auch aussieht, es ist alles mit Nachkommastellen berechnet. Du hast von Punkt A nach Punkt B 5-Pixel weit gezeichnet. Intern kann die Position B aber ein Wert mit Dezimalstellen sein. |
AW: Canvas - gleichschenkliches gefülltes Dreieck
Liste der Anhänge anzeigen (Anzahl: 1)
Ja, das ist schon klar. Dass der Canvas Pixel darstellt ist ja bekannt.
Ich hätte mir gewünscht, dass das Dreieck so aussieht, wie im Anhang. Das wäre ja auch nicht unlogisch. Ok, dann muss man das vermutlich explizit als Anforderung berücksichtigen. @himitsu Dein Beispiel sieht gut aus. Aber größere Dreiecke können auch besser dargestellt werden. |
AW: Canvas - gleichschenkliches gefülltes Dreieck
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Hier noch mal was ich meinte. Dieses Dreieck (siehe Anhang) besteht aus zwei übereignender liegenden Dreiecken. Beide haben die gleichen Koordinate, nur hat das eine einen Pinsel der Breit 4 Pixel, das andere einen Pinsel der Breite 1 Pixel. Sie sind nicht symmetrisch, obwohl die Koordinate identisch sind. Also wenn du verstanden hast, dass ich dir sagen wollte, dass Canvas Pixel darstellen kann, dann weiß ich was du verstanden hast. //Edit: Andere Grafik eingefügt. Sie zeigt besser was ich meine. |
AW: Canvas - gleichschenkliches gefülltes Dreieck
Nichtmal "austricksen" lässt sich die Zeichenroutine. :stupid:
Delphi-Quellcode:
Da bleibt dann wohl nur selber malen. (Pixel für Pixel)
Canvas.MoveTo(A[0].X, A[0].Y);
Canvas.LineTo(A[1].X, A[1].Y); Canvas.LineTo(A[2].X, A[2].Y); Canvas.MoveTo(A[0].X, A[0].Y); Canvas.LineTo(A[2].X, A[2].Y); |
AW: Canvas - gleichschenkliches gefülltes Dreieck
Oder um es mal laienhaft auszudrücken: Bei eine schrägen Linie mit der Stärke ein Pixel springen die Pixel eben etwas hin und her. Bei einer längeren und oder breiteren Linie fällt es nicht so stark auf, wenn man nicht gerade mit der Nase vorm Bildschirm hängt. Um den Effekt etwas abzuschwächen gibt es die Kantenglättung oder Antialiasing. Das funktioniert aber nur wenn die Linie entsprechen breit ist. Bei der Stärke von einem Pixel kann die Kantenglättung auch nichts mehr reißen.
Aber die Grafik ist doch nur 5x5 Pixel groß. Da kann man doch die Pixel einzeln setzen. Wenn du mehrere Grafiken zeichnen willst, dann hinterleg sie als "Zeichenvorschrift" in einer entsprechenden Datenstruktur. Oder binde entsprechende Bitmaps als Ressource ein. |
AW: Canvas - gleichschenkliches gefülltes Dreieck
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab mal gezeichnet:
|
AW: Canvas - gleichschenkliches gefülltes Dreieck
Ich danke Euch.
Die Pinselstärke habe ich mal gedanklich ausgenommen, da die hier nicht relevant ist. Letztlich gibt es Algorithmen für Linien, die ein Pixel (das rechnerisch bei 3,5 liegen würde) auf 3 oder auf 4 setzen. Das ist logisch. Dass es mir als Betrachter lieber wäre das untere auf 3 und das obere auf 4 zu setzen, kann die Polygon-Funktion ja nicht wissen. Dazu müsste ich eben eine GleichschenklichesDreieck-Funktion schreiben oder benutzen (oder fixe Bitmaps oder Pfade). Insofern schließe ich mich hier Luckie komplett an. Ich war nur zunächst von dem etwas unschönen Ergebnis überrascht und dachte, ich müsste vielleicht noch einen bestimmten Endpunkt festlegen oder so. Oder dass ein anderer Fehler vorlag. Jetzt sehe ich, dass "mein spezielles" Wunschpolygon mit der Standardfunktion so nicht zu erreichen ist. Also lasse ich es so oder entscheide mich irgendwann für eine genauere Lösung. |
AW: Canvas - gleichschenkliches gefülltes Dreieck
Der Algo müsste praktisch einen Mittelpunkt berechnen und von diesem Punkt aus gesehn alle Punkte eher aufrunden, als abzurunden. (mit Bankers-Round würde das ganze noch unvorhersehbarer und sieht gleich anders aus, nur weil man das Bild um 1-2 Pixel verschiebt)
|
AW: Canvas - gleichschenkliches gefülltes Dreieck
Zitat:
|
AW: Canvas - gleichschenkliches gefülltes Dreieck
Mit dem Bresenham-Algorithmus wäre das vermutlich nicht passiert. Der wird aber wohl nicht angewandt, weil es schnellere Algorithmen gibt, aber sicher bin ich mir hier nicht. Die Vorgehensweise bei dem Algorithmus ist jedenfalls so, das alle Linien zunächst auf den Bereich (x>0, y>0, Steigung < 1) normalisiert werden und dadurch eigentlich gleiche Linien herauskommen müssten.
![]() Grundsätzlich ist es ja so: Um eine Linie von (0,0) nach (1,2) zu zeichnen kann man so vorgehen (0,0)-(1,1)-(1,2): Erst schräg nach oben dann nach rechts (0,0)-(0,1)-(1,2): Erst nach rechts, dann nach schräg oben Beide Pfade sind komplett gleichwertig. Wenn ein Algorithmus nun für eine Linie (0,0)-(1,2) die Variante #1 wählt, aber von (1,2)-(0,0) die Variante #2 hätte man schon eine Asymmetrie. Nicht umsonst ist das Rendern von Fonts im Pixelbereich so schwer und gelingt kaum so, das die Buchstaben dann noch symmetrisch sind. Es geht halbwegs, aber dazu sind die einzelnen Buchstaben mit so.g. 'Hints' versehen, die dem Renderer z.B. sagen, das bei dem Dreicke die linke und rechte Schräge Linie symmetrisch sein sollen, und dann kann er das entsprechend rendern. Ob intern in der Canvas-Paint.Methode mit Nachkommastellen gearbeitet wird, wage ich zu bezweifeln. |
AW: Canvas - gleichschenkliches gefülltes Dreieck
Danke. Das klingt plausibel und ist (auch für mich) verständlich. :-)
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:18 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz