Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Ellipsenalgo aus Formelsammlung kreieren (https://www.delphipraxis.net/217478-ellipsenalgo-aus-formelsammlung-kreieren.html)

delphifan2004 8. Jul 2025 10:31

Ellipsenalgo aus Formelsammlung kreieren
 
Hallo

Ich habe ausgehend von der Ellipsengleichung: (Quelle: Hans Jochen Bartsch "Taschenbuch Mathematische Formeln für Ingenieure und Naturwissenschaftler"

sqr(x)/sqr(a) + sqr(y)/sqr(b) = 1

nach y aufgelöst:

y = +/- (b/a)*sqrt(sqr(a)-sqr(x))


folgendes Programm erstellt:

Delphi-Quellcode:
procedure DrawEllipse(xm,ym,xR,yR,stangle,endangle: Extended);
var
  angle: extended;
  a,b,x: extended;
  yp,yn: Extended;
  px,py: int64;
begin
  angle := 0.0;
  angle := stangle;
  x := xm; y := ym;  //Mittelpinkt der Ellipse
  a := xR; b := yR;  //a und b --- x- und y Readien der Ellipse
  while angle < endangle do //hier aber Winkel als Laufvariable benutzt
  begin
    a := x / cos(angle); b := y / sin(angle);     //x = a * cos(angle); y = b * sin(angle)
    yp := b/a * sqrt(sqr(a)-sqr(x));               //der Punkt der Ellipse an der Position X
    py := Round(yp);                               //auf Integer gerundet und wegen Int64 als Rückgabewert
    DrawPixel(x,Longword(yp))                      //auf Longword gecastet
    yn := -b/a * sqrt(sqr(a)-sqr(x));              //gleicher Ablauf
    py := round(yp);                               //für die negative Halbachse
  end;
end;
Da wird aber x ncht verändert, was naxh meinem Verständnis aber der Fall sein sollte wenn ich weigstens eine halbe Ellipse zeichnen will.
Ich verwende den Winkel als Laufvariable, habe aber ein "Brett vorm Kopp" wegen Laufvariale x die ja mit dem Winkel verändert werden muss.

wie kann ich möglichst effektiv die Gleicung so umstellen dass ich trotz Winkel als Laufvarible den Parameter X ebenfalls weiter zähle. Irgendwie habe ich im Moment einen Knoten im Kopf.

Renate Schaaf 8. Jul 2025 11:20

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Du musst x und y als Funktion von angle haben, dann kannst Du für jeden Wert von angle den Punkt (x,y) zeichnen.

Hier ist ein bisschen Mathe dafür, kannst aber auch Ellipse und Polarkoordinaten googeln.

r ist der Abstand vom Mittelpunkt. X = x-xm Y = y - xm

X = r*cos(angle) Y = r* sin(angle)

Löse X^2/a^2 + Y^2/b^2 = 1 nach r auf:

r = a*b/(sqrt(sqr(b*cos(angle))+ sqr(a*sin(angle)))

Dabei kann man auch noch sqr(sin(angle)) durch 1 - sqr(cos(angle)) ersetzen.

Jetzt (x,y) = (xm,ym) + (r*cos(angle), r*sin(angle)) in Abhängigkeit von angle zeichen.

Kas Ob. 8. Jul 2025 11:26

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Hi,

You have to distinguish (x,y) from (x0,y0) "ellipse center", you already have (xm,ym) which is (x0,y0).

After than it is easy to draw the pixel (X,Y)
X = x0 + x(angle)
Y = y0 + y(angle)

In other words, the naming of the variables is deceiving you, if it is yp or yn ?!

Another thing: you are drawing both +- values so it will mirrored, use one value (the positive) and walk the angle with refined (small enough) step per radius.

himitsu 8. Jul 2025 11:40

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Wirklich unbedingt "selbst Pixel für Pixel" :?:

TCanvas.Ellipse für einen Kreis, bzw. eine Ellipse
und Vcl.Graphics.TCanvas.Arc für einen Bogen (Teil eines Kreises/Ellipse)

Delphi-Referenz durchsuchenVcl.Graphics.TCanvas.Ellipse
Delphi-Referenz durchsuchenVcl.Graphics.TCanvas.Arc



PS: py und yn sind doch etwas "nutzlos", da sie (ihr Inhalt) niemals verwendet werden,
und ich bin mir fast sicher, dass der Compilier es dir eigentlich auch mitteilen sollte. (falls jemand die Compilerwarnungen liest)

py, vor dem DrawPixel ist auch nutzlos.
Sicher, dass danach bei Longword(yp) nicht py anstatt yp gemeint ist?

Sowie die a und b, vor der Schleife, auch noch.

Wobei es ja bereits beim invaliden "CAST"
Delphi-Quellcode:
Longword(yp)
abgeraut sein wird
und natürlich beim nichtdeklarieren
Delphi-Quellcode:
y
.



Sicher, dass deine Übersetzung so wirklich allgemein nicht irgendwelche groben Überlegungs-/Übersetzungsfehler (Formel zu Code) besitzt, als nur das eine fehlende X?

Delphi.Narium 8. Jul 2025 11:49

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Wenn zu Beginn diese Bedingung
Delphi-Quellcode:
while angle < endangle do
erfüllt ist, müsstest Du in eine Endlosschleife laufen, da angle in der Schleife nicht verändert wird und von daher die Abbruchbedingung der Schleife nie erfüllt sein wird.

Eine Zuweisung auf x erfolgt nur vor der Schleife:
Delphi-Quellcode:
x := xm;
. Danach wird x nicht mehr verändert, von daher muss x immer gleich bleiben.

Gibt der Kompiler irgendwelche Warnungen aus, z. B. dass der auf eine Variabel zugewiesene Wert nie benutzt wird? Das sollte (mindestens) bei angel, a, b und py eigentlich der Fall sein.

Bist Du sicher, dass die Formelauflösung nach y korrekt ist?

Delphi-Quellcode:
y = ±b * sqrt(1 - sqr(x) / sqr(a))

Renate Schaaf 8. Jul 2025 12:57

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Der code muss sowieso neu geschrieben werden. Hier ist ein Beispiel (ungetestet)

Delphi-Quellcode:
//Zeichne Ellispe zwischen stangle und endangle mit Winkelschrittweite AngleStep
procedure DrawEllipse(xm,ym,xR,yR,stangle,endangle,AngleStep: Extended);
var
  angle: extended;
  a,b,x,y,r: extended;
begin
  angle := stangle;
  a := xR; b := yR; //a und b --- x- und y Readien der Ellipse
  while angle < endangle do
  begin
    r := a*b/sqrt(sqr(b*cos(angle))+sqr(a*sin(angle)));
    x := xm + r*cos(angle);
    y := ym + r*sin(angle);
    DrawPixel(round(x), round(y)); //was auch immer das ist :)
    angle:=angle+AngleStep;
  end;
end;
extended ist meiner Meinung nach übertrieben genau.
Achtung: angle muss in radians angegeben werden, also 360° = 2*Pi
Statt sin, cos kann man auch SinCos aus der math-unit verwenden.

Renate

Rollo62 8. Jul 2025 13:07

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Vielleicht ist es besser, die Laufvariable parametrisch zu Normieren und nicht als Winkel zu übernehmen.
Dann kann man das Rendering etwass besser steuern.

So ungefähr meine ich, ungetestet:

Delphi-Quellcode:
// Zeichnet eine Ellipse mit Mittelpunkt (xm, ym), Radien xR, yR,
// zwischen Startwinkel stangle und Endwinkel endangle (in Grad),
// mit numSteps Schritten für gleichmäßigere Punktverteilung
procedure DrawEllipse(xm, ym, xR, yR, stangle, endangle: Extended; numSteps: Integer);
var
  t, tStart, tEnd, tStep: Extended;
  i: Integer;
  x, y: Extended;
begin
  if numSteps < 1 then Exit; // Sicherheitsprüfung

  // Winkel in Radiant umrechnen
  tStart := DegToRad(stangle);
  tEnd := DegToRad(endangle);
 
  // Normierter Parameter t von tStart bis tEnd
  tStep := (tEnd - tStart) / numSteps;

  // Zeichne Punkte entlang der Ellipse
  for i := 0 to numSteps do
  begin
    t := tStart + i * tStep;
    // Parametrische Darstellung der Ellipse
    x := xm + xR * Cos(t);
    y := ym + yR * Sin(t);
    DrawPixel(Round(x), Round(y)); // Zeichne Pixel
  end;
end;

Renate Schaaf 8. Jul 2025 15:44

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Zitat:

Zitat:

Zitat von Rollo62 (Beitrag 1550035)
Vielleicht ist es besser, die Laufvariable parametrisch zu Normieren und nicht als Winkel zu übernehmen.
Dann kann man das Rendering etwass besser steuern.

Delphi-Quellcode:

    x := xm + xR * Cos(t);
    y := ym + yR * Sin(t);


:oops::oops::oops:

Das hatte ich glatt vergessen ... Ja, die Schritte eingeben ist immer besser.

delphifan2004 8. Jul 2025 20:09

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Danke an Euch alle! So wird meine Ellipse gezeichnet. Mit 4096 Schritten passiert das lückenlos.

Wenn ich dieStart und Endwinkel direkt eingebe wird erst der untere Ellipsenbogen gezeichnet, dann der obere. Wenn ich zuerst den oberen Ellipsenbogen oder Teile davon gezeichnet haben will, muss ich die Einkelangaben noch mit (-1) multiplizieren.

@himitsu: Ja, Delphi kann das auch aber ich wollte ja gerade wissen wie das Delphi intern macht und dazu ist die Ellipsengleiching notwendig. Dennoch Danke, wie auch an alle Anderen hier die mir geholfen haben. Ich habe jetzt @Renate Schaaf's Entwurf ergänzt um @Rolle72's NumStep im Test.

Danke wie verrückt. Morgen guck ich mir die nach x und y aufgelösten Gleichungen an und gehe das noch mal auf dem Papier durch. :bounce1:

Renate Schaaf 8. Jul 2025 20:24

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Zitat:

Zitat von delphifan2004 (Beitrag 1550045)
Danke an Euch alle! So wird meine Ellipse gezeichnet. Mit 4096 Schritten passiert das lückenlos.

Wenn ich dieStart und Endwinkel direkt eingebe wird erst der untere Ellipsenbogen gezeichnet, dann der obere. Wenn ich zuerst den oberen Ellipsenbogen oder Teile davon gezeichnet haben will, muss ich die Einkelangaben noch mit (-1) multiplizieren.

@himitsu: Ja, Delphi kann das auch aber ich wollte ja gerade wissen wie das Delphi intern macht und dazu ist die Ellipsengleiching notwendig. Dennoch Danke, wie auch an alle Anderen hier die mir geholfen haben. Ich habe jetzt @Renate Schaaf's Entwurf ergänzt um @Rolle72's NumStep im Test.

Danke wie verrückt. Morgen guck ich mir die nach x und y aufgelösten Gleichungen an und gehe das noch mal auf dem Papier durch. :bounce1:

Nimm alles von Rollo! Meine Formel kommt auch zum Ziel, aber spiralförmig statt geradezu. :wink:

Natürlich! Canvas-y geht ja von oben nach unten. Also angle für wie die Uhr geht, und -angle andersrum.

Rollo62 9. Jul 2025 08:39

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Zitat:

Zitat von delphifan2004 (Beitrag 1550045)
Danke an Euch alle! So wird meine Ellipse gezeichnet. Mit 4096 Schritten passiert das lückenlos.

Genau, das ist generell die Problematik bei diesen parametriesierten Methoden.
Man will die Schrittlänge, oder "Punktdichte" ja nicht jedes Mal von Hand optimieren und vorgeben.
Bei kleinen Ellipsen sind 4096 vielleicht totaler Overhead, bei großen Ellipsen kommt es vielleicht gerade mal so hin.

Die Frage wäre deshalb, wie berechne ich die Schritte immer optimal, z.B. anhand einer gewünschten "Punktdichte" für alle Zeichenelemente auf dem Canvas ?

Dazu fallen mir mindestens 3 Alternativen ein, die aber alle nicht ideal sind, weil sie sqrt und trigonometrische Funktionen nutzen können.

Grundsätzlich denke ich, gibt es:
A.) Entweder vor dem eigentlichen Zeichen berechen/abschätzen

Delphi-Quellcode:

    function CalcNumSteps(a, b, stAngleDeg, endAngleDeg: Extended; dMax: Integer): Integer;
Das kann spitze Enden aber womöglich nicht dicht genug abbilden.

oder

B.) iterativ innerhalb der Zeichenschleife anhand der Teilstücke berechnen.
Damit könnte zumindest die "Punktdichte" auch variieren, z.B. bei extrem unsymmetrischen Ellipsen.

Vielleicht gibt es dafür ja auch eine möglichst effiziente Methode, die ich nicht kenne?

dummzeuch 9. Jul 2025 09:39

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Zitat:

Zitat von Renate Schaaf (Beitrag 1550040)
Zitat:

Zitat:

Zitat von Rollo62 (Beitrag 1550035)
Vielleicht ist es besser, die Laufvariable parametrisch zu Normieren und nicht als Winkel zu übernehmen.
Dann kann man das Rendering etwass besser steuern.

Delphi-Quellcode:

    x := xm + xR * Cos(t);
    y := ym + yR * Sin(t);



Wo ich das gerade lese: Es gibt in Math eine Funktion SinCos, die Cos und Sin gleichzeitig berechnet und dadurch effizienter ist.

freimatz 9. Jul 2025 09:56

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Zitat:

Zitat von delphifan2004 (Beitrag 1550045)
@himitsu: Ja, Delphi kann das auch aber ich wollte ja gerade wissen wie das Delphi intern macht und dazu ist die Ellipsengleiching notwendig.

Delphi macht das intern sicher anders. Dazu müsste man in dessen Code schauen.

Kas Ob. 9. Jul 2025 10:08

AW: Ellipsenalgo aus Formelsammlung kreieren
 
the Step should be calculated from the drawing function not to be supplied with a, b, startangle and endangle, unless you want to draw points instead of continuous line, and it should be calculated from the radius, the radius here is Sqrt(a^2+b^2)

Step = 1/Sqrt(a^2+b^2)

and that it is for continuous line, if you want a dotted draw then make the passed parameter with coefficient as factor to the step so it will be

Step = StepMultiplier/Sqrt(a^2+b^2)

Rollo62 9. Jul 2025 15:53

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Zitat:

Zitat von Kas Ob. (Beitrag 1550052)
Step = 1/Sqrt(a^2+b^2)

Like said, it is the sqrt that makes me nervous, but its maybe needed here.
I think it depends a lot on the shape, how to handle it.
For lines, circles, squares, a pre-calculated step will work nicely.
For ellipses and other complex paths, maybe you always need varying step-sizes during drawing.

Kas Ob. 9. Jul 2025 16:26

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Zitat:

Zitat von Rollo62 (Beitrag 1550055)
Zitat:

Zitat von Kas Ob. (Beitrag 1550052)
Step = 1/Sqrt(a^2+b^2)

Like said, it is the sqrt that makes me nervous, but its maybe needed here.
I think it depends a lot on the shape, how to handle it.
For lines, circles, squares, a pre-calculated step will work nicely.
For ellipses and other complex paths, maybe you always need varying step-sizes during drawing.

A overdraw pixel will happen for the suggested above for sure, but it will not affect the drawing, the only enhancement to do is to check if x and y changed from last pixel/point then draw, due to approximation of course, as for dynamic, it will return to the same check no matter what algorithm been used, for more accurate approximation you need to calculate the derivative of the speed of pixel on the slope then divide it by the radius, but not that radius you will calculate from (0,0) the center of the ellipse, this will be more complex for no, benefit visually or not.

the only case when it corrupt drawing is when the ellipse is more like a line then an ellipse, when one of the axis is barely moving while the other taking the full speed for the next step.

Kas Ob. 9. Jul 2025 16:30

AW: Ellipsenalgo aus Formelsammlung kreieren
 
To calculate this accurately you need to take the last used step then calculate the length to move for current pixel based on the last step, draw it then adjust the step for the next one, so in theory we will be calculating the step for the next pixel but not for the current one.

after calculating the distance from the last pixel divide by the radius and use it for the next pixel.

Rollo62 9. Jul 2025 16:55

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Zitat:

Zitat von Kas Ob. (Beitrag 1550057)
the only case when it corrupt drawing is when the ellipse is more like a line then an ellipse, when one of the axis is barely moving while the other taking the full speed for the next step.

Yes, thats what I meant.
An algorithm sould be univeral and not break when it comes closer to extreme settings.
https://www.geogebra.org/m/AAx6FWka

If the dot is on top side, each of its step is maybe set to be dense enough.
If the dot is in right side, anbd the ellipse not very high, then the density will increase a lot, perhaps too dense.

Either you can accept these changes in density, or you try to optimize it in each step.
The whole world is a compromize :-D

Maybe one solution would be to divide the ellipse into sections, where its equal to circle, where its more dense and where its not so dense, for switching to different optimized algorithms in each segment.

Kas Ob. 9. Jul 2025 17:31

AW: Ellipsenalgo aus Formelsammlung kreieren
 
Zitat:

Zitat von Rollo62 (Beitrag 1550061)
Maybe one solution would be to divide the ellipse into sections, where its equal to circle, where its more dense and where its not so dense, for switching to different optimized algorithms in each segment.

Think about it, no matter how much you divide it will return to check against the last pixel or calculating the new (next) pixel distance form the current:
1) in the first it is easier to simply compare (new pixel vs last pixel) then adjust.
2) in the other you must have the distance is close enough to 1 in four straight direction (up, down, left and right) and close enough to sqrt(2) in 4 diagonal direction, any less than that we are drawing on top of the current (or the last), any bigger we are skipping.

Whole problem is due the arithmetic is in float numbers while drawing and coordination in integers.

i don't think that there is quite real one liner algorithm that can be solve this.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:32 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