![]() |
Eine Eigene Linen Zeichnen ?
Hallo,
da ich schon länger Zeit für verschiedene Zwecke eine eigene Linen Zeichne möchte, habe ich diese Code heute geschrieben:
Delphi-Quellcode:
Ich würde gerne von euch wisse, ob dieser Code alle Situationen Abdeckt und ob es "noch schneller" geht.
procedure DrawLinePluto(aCanvas:TCanvas; const x1,y1,x2,y2:Integer; PenColor:TColor);
var wx,wy:Integer; fx,fy,mx,my:Integer; begin wx:=abs(x2-x1); wy:=abs(y2-y1); fx:=x1; fy:=y1; if wx = 0 then mx:=0 else mx:=+1; if wy = 0 then my:=0 else my:=+1; while True do begin aCanvas.Pixels[fx,fy]:=PenColor; fx:=fx+mx; fy:=fy+my; if (my <> 0) and (fy = y2) then break; if (mx <> 0) and (fx = x2) then break; end; end; Im Internet habe ich leider nur sehr viele Beschreibungen gesehen, die mir zu Kompliziert beschrieben wahren. Ich möchte später nach einigen Tests, verschiedene Varianten von dieser Procedere erstellen. Z.b. Welche Die Mehrer Farben da stellen könne, im Moment kann die Line ja nur in einer Farbe da gestellt werden. Mein Ziel ist es mehrer Farben hinzubekommen, und mit Farb Muster und sowas. das ist aber nicht weiter schwierig. Was haltet ihr von der Procedere ? edit:
Delphi-Quellcode:
So diese Procedere kann jetzt auch mit Negativen Werten arbeiten(scheint auf jedenfall so)procedure DrawLinePluto(aCanvas:TCanvas; const x1,y1,x2,y2:Integer; PenColor:TColor); var wx,wy:Integer; fx,fy,mx,my:Integer; begin wx:=x2-x1; wy:=y2-y1; fx:=x1; fy:=y1; if wx = 0 then mx:=0 else mx:=+1; if wy = 0 then my:=0 else my:=+1; while True do begin aCanvas.Pixels[fx,fy]:=PenColor; if wx > 0 then fx:=fx+mx else fx:=fx-mx; if wy > 0 then fy:=fy+my else fy:=fy-my; if (my <> 0) and (fy = y2) then break; if (mx <> 0) and (fx = x2) then break; end; end; Edit2: Leider kann diese Procedere nur Perfekte Lienen da stellen, was aber nicht immer sinvoll ist. es werden keine "Treppen" Lienen gezeichnet. |
Re: Eine Eigene Linen Zeichnen ?
|
Re: Eine Eigene Linen Zeichnen ?
das weiß ich auch, aber dort kann man nicht ohne weiteres eine Line z.b. in mehrer Farben zeichnen ohne das mühevoll mit Polygonen oder anders zu lösen.
ich kenne die TCanvas Klasse sehr gut. Edit01: Erste Tests haben ergeben, das diese Procedere leider nicht mit negativen Zahlen umgehen kann. hat einer eine Idee wie ich das am einfachsten einbauen könnte ? |
Re: Eine Eigene Linen Zeichnen ?
Ich schätz mal das der Code hier
Delphi-Quellcode:
das gleiche macht wie deiner... :idea:
procedure DrawLine(aCanvas: TCanvas ; x1,y1,x2,y2: Integer ; color: TColor);
var crntColor: TColor; begin crntColor := aCanvas.Pen.Color; aCanvas.Pen.Color := color; aCanvas.MoveTo(x1,y1); aCanvas.LineTo(x2,y2); aCanvas.Pen.Color := crntColor; end; wegen den negativen zahlen: Im Form links oben ist (0|0) weiter nach links gehts in dem fall nicht. Du müsstest da dann ein Offset einbauen das bspw. gezeichnet 50 gerechnet 0 ist. |
Re: Eine Eigene Linen Zeichnen ?
Zitat:
folgender Aufruf klappt (verständlicher Weise) nicht:
Delphi-Quellcode:
es wird eine Linie gezeichnet im 45 Grad Winkel aber nicht zu dem Punkt den ich angegeben habe. Die Funktion ist so nutzlos, die Logic stimmt einfach nicht.
DrawLinePluto(Self.Canvas, 0, 0, 150, 600, clBlue);
Dein Quelltext bewirkt das du eintweder in jedem Schritt 1 oder gar kein Pixel nach Rechts und unten gehst. Das bewirkt logischer Weise ein 45 Grad Winkel oder 0 Grad. |
Re: Eine Eigene Linen Zeichnen ?
Ja ! da gebe ich dir Recht.
Aber ich möchte ja später die Möglichkeit haben eine mehrfarbige Line zu gestalten das ist mit MoveTo und LieneTo leider sehr aufwendig. und mit Poligonen möchte ich das erst recht nicht machen. Außerdem möchte ich selber verstehen wie ein DDA Algorithmus arbeitet . Es gibt für viele mehrer Möglichkeiten je nach dem was man gerade braucht bzw. machen möchte. Wie mein Zweck eignet sich MoveTo und LineTo leider nicht. es sei denn man kann irgendwie mit nur einem Procedere Aufruf mehrfarbig zeichnen. edit: was schlägst du also vor ? |
Re: Eine Eigene Linen Zeichnen ?
ich schlage eine Verhältnisgleichung vor.
Wenn eine Linie von x1 nach x2 gezeichnet werden soll dann muss x bei der hälfte der Stecke auch auf der y-Achse die hälfte der Stecke zurück gelegt haben. |
Re: Eine Eigene Linen Zeichnen ?
Ja das ist logisch..... und weiter ?
edit: Aber das mache ich doch schon im Prinzip ? beide Variablen werden um den gleichen Faktor erhört..... |
Re: Eine Eigene Linen Zeichnen ?
du erhöhst nicht um einen Factor sondern um 1 oder 0
|
Re: Eine Eigene Linen Zeichnen ?
wie meinst du das ?
Wenn es eine Negative Line ist verringere ich den "Faktor" und wenn es eine Positive ist erhöhe ist sie. Aber was müsste ich jetzt genau ändern damit das klappt ? |
Re: Eine Eigene Linen Zeichnen ?
probier mal folgende Funktion:
Delphi-Quellcode:
Wie bereits erwähnt geht es hier um ein Verhältnis damit die Linie nicht 45 Grad wird und nicht wie du es machst entweder +1 oder 0. Sondern der X Punkt muss sich zum Y Punkt in dem Verhältnis ändern wie das Verhältnis der Länge der Linien ist.
procedure DrawLine(ACanvas: TCanvas; x1, y1, x2, y2: Integer; AColor: TColor);
var lCount, lDistanceX, lDistanceY, lStepSize : Integer; begin lDistanceX := x2 - x1; lDistanceY := y2 - y1; if Abs(x2 - x1) < Abs(y2 - y1) then begin lCount := 0; if (lDistanceY > 0) then lStepSize := +1 else lStepSize := -1; while (lCount <> lDistanceY) do begin ACanvas.Pixels[x1 + Trunc(lCount * lDistanceX / lDistanceY), y1 + lCount] := AColor; lCount := lCount + lStepSize; end; end else begin lCount := 0; if (lDistanceX > 0) then lStepSize := +1 else lStepSize := -1; while (lCount <> lDistanceX) do begin ACanvas.Pixels[x1 + lCount, y1 + Trunc(lCount * lDistanceY / lDistanceX)] := AColor; lCount := lCount + lStepSize; end; end; ACanvas.Pixels[x2, y2] := AColor; end; |
Re: Eine Eigene Linen Zeichnen ?
BESTEN DANK ! Ich werde ihn mir mal genau ansehen.
|
Re: Eine Eigene Linen Zeichnen ?
wie gesagt. Es geht darum im Verhältnis etwas zu berechnen.
Wenn du zum Beispiel eine Linie von x: 0 - y: 0 nach x: 10 - y: 40 zeichnen willst, musst du bei jedem Schritt auf der X-Achse 4 Schritte auf der Y-Achse gehen. Du musst also das Verhältnis der X-Distance zur Y-Distance gleich setzen mit dem SchrittX zu SchrittY. Nennt sich glaub ich auch Dreiecksgleichung. Wenn du später mal eine Linie mit Farbverlauf zeichnen willst musst du die Farbanzteile zur Länge der Linie ebenso ins Verhältnis setzen. |
Re: Eine Eigene Linen Zeichnen ?
Liste der Anhänge anzeigen (Anzahl: 1)
Hier mal die alte Demo von mir mit den Marching Ants. Da ist noch eine andere Möglichkeit aufgezeigt.
/EDIT: Aber basiert auf einem WinAPI Befehl! |
Re: Eine Eigene Linen Zeichnen ?
Danke Muetze1 werde ich mir gleich mal ansehen.
Ich finde dieses Thema im Moment recht Intressant, weil ich mich in den letzten 10 Jahren wo ich mit Object Pascal arbeite damit mich noch nie befast habe. Später geht es mir auch noch um andere Figuren wie z.b. Kreise, Vierecke, Abgerundete Ecken.... Aber erstmal die Line mein Ziel ist es in erster Line SirThornberry Procedure so zu erweitern, das ich Linen Style verwenden kann(eigene) und natürlich Farb Style die man mit den Linen Style Verbinden kann. Wie das geht weiß ich schon. Kennt jemand von euch ein Tutorial was das gut beschreibt ? also mit einfachen Wörtern die jeder "normale" Mensch versteht ? Weil auf den meisten seiten die ich zum Thema gefunden habe, wird leider alles über Formulen erklärt, aber ich habe keine Idee, wie man diese Formueln verstehen soll.... Wie gesagt, ich möchte dieses Thema verstehen..... |
Re: Eine Eigene Linen Zeichnen ?
ich habe in deiner Pas Datei gesehen, das du
LineDDA benutz, was mir nicht viel Weiter hilf. Ich wollte ja eine eigene Funktion, Ich meine diese Procedure gibt es auch für Lazarus. Trotzdem Danke ! |
Re: Eine Eigene Linen Zeichnen ?
ich habe jetzt die Procedure erweitert von:SirThornberry Vielen Dank noch mal für dein Code.
Delphi-Quellcode:
Nun Kann sie mit Farb Stylen und Linen Stylen umgehen*freu*
procedure DrawLine(ACanvas: TCanvas; x1, y1, x2, y2: Integer; AColor: TColor; style:array of Boolean; FarbStyle:array of TColor);
procedure StyleFarbeLine(var zc,zw,z,lenStyle, lenColor,W:Integer); begin if (lenStyle > -1) and (lenColor > 0) then begin if zc +1 <= lenColor then inc(zc) else zc:=0; end; // lenColor if lenStyle > -1 then begin if z +1 <= Length(style) then inc(z) else z:=0; end; // lenStyle if (lenStyle = -1) and (lenColor > 0) then begin if zw+1 >= w then begin zw:=0; if zc+1 <=lenColor then inc(zc); end else inc(zw); end; end; var lCount,lDistanceX,lDistanceY,lStepSize: Integer; z,zc,lenColor,lenStyle,w,zw:Integer; lc:TColor; begin lDistanceX := x2 - x1; lDistanceY := y2 - y1; z:=0; zc:=0; zw:=0; lenColor:=Length(FarbStyle); lenStyle:=Length(style)-1; if lenColor = -1 then lc:=AColor; if Abs(x2 - x1) < Abs(y2 - y1) then begin lCount := 0; if (lDistanceY > 0) then lStepSize := +1 else lStepSize := -1; w:=abs(lDistanceY div lenColor); while (lCount <> lDistanceY) do begin if lenColor > 0 then lc:=FarbStyle[zc]; if (lenStyle = -1) or (lenStyle >= 0) and (style[z]) then ACanvas.Pixels[x1 + Trunc(lCount * lDistanceX / lDistanceY), y1 + lCount] := lc; StyleFarbeLine(zc,zw,z,lenStyle,lenColor,w); lCount := lCount + lStepSize; end; end else begin lCount := 0; if (lDistanceX > 0) then lStepSize := +1 else lStepSize := -1; w:=abs(lDistanceX div lenColor); while (lCount <> lDistanceX) do begin if lenColor > 0 then lc:=FarbStyle[zc]; if (lenStyle = -1) or (lenStyle >= 0) and (style[z]) then ACanvas.Pixels[x1 + lCount, y1 + Trunc(lCount * lDistanceY / lDistanceX)] := lc; StyleFarbeLine(zc,zw,z,lenStyle,lenColor,w); lCount := lCount + lStepSize; end; end; ACanvas.Pixels[x2, y2] := AColor; end; // Beispiel Aufruf: DrawLine(PaintBox1.Canvas,mx,my,x,y,clRed,[],[clred,clBlue,clYellow]); Edit00: Proceure geändert. Edit01: Neue Version von der Proceure: Jetzt dürfte alles klappen. Ich hatte im Obigen teil ein abs vergessen bei der w Zuweisung. |
Re: Eine Eigene Linen Zeichnen ?
Zitat:
Und warum sollte dir die Funktion (neben dem eben erwähnten) denn nicht helfen? Die Funktion implementiert den Linien-zeichnen Algorithmus und berechnet jeden einzelnen Punkt, welcher zu Zeichnen ist und ruft zum zeichnen jeweils die angegebene Funktion auf. Somit kannst du doch deinen Style/Farbe etc frei anpassen. Du wirst für jeden einzelnen Punkt aufgerufen. Von daher kapier ich deinen Einwand nicht oder du hast die Funktion nicht im Detail verstanden. |
Re: Eine Eigene Linen Zeichnen ?
ehrlich gesagt, habe ich mir die Funktion lineDDA gar nicht angesehen....
ich habe nur die Parameter gesehen und das reichte mir schon. Du meinst damit ist sowas schon möglich ? von Windows aus ? Bunte Linen ? |
Re: Eine Eigene Linen Zeichnen ?
so wie ich muetze verstanden habe gibt man eine callbackmethode an welche dann für das zeichnen jedes pixels aufgerufen wird
|
Re: Eine Eigene Linen Zeichnen ?
Zitat:
/EDIT: roter Kasten? SirThomberry trifft es genau. |
Re: Eine Eigene Linen Zeichnen ?
ich habe mir dein Beispiel noch einmal angesehen und mir ist ein Licht aufgegangen...
Aber leider nützt er mir wenig da ich unter Lazarus keine LineDDA Procedure habe. Ich könnte allerdings den Code entsprechend umbauen... Wenn ich wollte. Naja, dann nochmal VIELEN DANK. ich glaube jetzt weiß ich wie LineDDA Arbeitet, hatte es beim ersten hinsehen nicht ganz verstanden aber jetzt schon. Unter Delphi währe das eine Erleichterung gewesen. |
Re: Eine Eigene Linen Zeichnen ?
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Aber nun habe ich in der Zwischenzeit mal ein Beispiel von dem Marching Ants Beispiel abgeleitet mit einer bunten Linie. Vielleicht hilft es dir ja, um die Farbwerte zu bilden. |
Re: Eine Eigene Linen Zeichnen ?
nicht schlecht... das habe ich so hinbekommen:
Delphi-Quellcode:
Auf diese art und weise kann ich ebenfalls ein Viereck zeichnen....
procedure DrawRect(const aCanvas:TCanvas; const x1,y1,x2,y2:Integer; const AColor: TColor; const LinenStyle:array of Boolean; const FarbSyle:array of TColor);
begin // Oben DrawLine(aCanvas,x1,y1,x2,y1,AColor,LinenStyle,FarbSyle); // Unten DrawLine(aCanvas,x1,y2,x2,y2,AColor,LinenStyle,FarbSyle); // Links DrawLine(aCanvas,x1,y1,x1,y2,AColor,LinenStyle,FarbSyle); // Rechts DrawLine(aCanvas,x2,y1,x2,y2,AColor,LinenStyle,FarbSyle); end; Was mit Bunten Linen und Stylen klar kommt. Das einzigte Problem was ich noch haben sind Füllmuster. |
Re: Eine Eigene Linen Zeichnen ?
Schau Dir einfach den Bresenham-Algorithmus an, das ist eigentlich der Algorithmus, der in so ziemlich heder Graphics-Engine implementiert ist. Er benötigt keine Floatingpoint-Mathematik und ist imho der schnellste Algorithmus.
![]() ![]() |
Re: Eine Eigene Linen Zeichnen ?
Floatingpoint-Mathematik
die kenne ich gar nicht.... Danke ! Den Wiki Aktikel kannte ich schon, der hat mir nicht weiter geholfen, wegen den Formeln die ich verstehe, weil ich nicht weiß wie ich sie lesen muss Der Andere link könnte Hilfreich sein. Vielen Dank dafür..... Weil ich möchte wie schon gesagt noch weitere Figuren selbst zeichnen wie z.b. ein Kreis.Ich habe gelesen das kann der Bresenham-Algorithmus ebenfalls. edit00:
Delphi-Quellcode:
Diesen Teil verstehe icn noch nicht ganz: was passiert genau bei 2*(e+dy) ?
if dy >= 0 then // positive Steigung
if dx >= dy then // leichte positive Steigung for x := P1.X to P2.X do begin Plot(x,y); if 2*(e + dy) < dx then Inc(e,dy) else begin Inc(y); Inc(e, dy-dx); end; end else ich weiß das es sich hierbei um eine Berechnung handelt. aber zu welchem Zweck ? |
Re: Eine Eigene Linen Zeichnen ?
Zitat:
Zitat:
Zitat:
|
Re: Eine Eigene Linen Zeichnen ?
naja, dann muss ich die Funktion mal bei Gelegenheit auseinander nehmen, Zeile für Zeile.
Aber die Beispiel Soruce Sagen mir im Moment recht wenig. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:00 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 by Thomas Breitkreuz