Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Vektorklasse mit echten Operatoren (https://www.delphipraxis.net/179570-vektorklasse-mit-echten-operatoren.html)

cltom 17. Mär 2014 12:09

Delphi-Version: XE2

Vektorklasse mit echten Operatoren
 
Hallo,

das Thema gibt es sicher schon, ich konnte es aber nicht finden. Irgendwo hab ich hier gesehen, wie man eine Klasse für Vektorrechnung so umsetzt, dass Operatoren wie +/-/x/... richtig interpretiert werden, sodass man nicht schreiben muss: cVektor := vadd(aVector, bVector) sondern einfach cVektor = aVektor + bVektor und die Funktion rechnet dann entsprechend.

sorry, wenn es jetzt doch leicht zu finden ist und danke
gruß
cltom

Namenloser 17. Mär 2014 12:14

AW: Vektorklasse mit echten Operatoren
 
Das geht nur mit Records, nicht mit Klassen, und man nennt das Überladene Operatoren. In dem Artikel steht eigentlich alles drin, was man braucht.

Panthrax 17. Mär 2014 13:30

AW: Vektorklasse mit echten Operatoren
 
Eine Beispiel-Implementierung um einDreieck um einen Punkt zu drehen; die Verwendung:
Delphi-Quellcode:
var
  Alpha: Extended;
  O, X, Y, Z: TVector2D;
  U, V, W: TPoint;
begin
  Alpha := 0; // Drehwinkel
  O := TVector2D.New(200, 200); // Ortsvektor zum Drehpunkt
  X := TVector2D.New(-80, 0); // Dreieckspunkte relativ zum Drehpunkt
  Y := TVector2D.New(0, -80);
  Z := TVector2D.New(80, 0);

  { Das Dreieck erst drehen, dann um den Ortsvektor verschieben; denn:
  O + X.Rotated(Alpha) <> (O + X).Rotated(Alpha). }
  U := O + X.Rotated(Alpha);
  V := O + Y.Rotated(Alpha);
  W := O + Z.Rotated(Alpha);

  Image1.Canvas.Polygon([U, V, W]);
end;

Uwe Raabe 17. Mär 2014 13:47

AW: Vektorklasse mit echten Operatoren
 
Ich hatte sowas schon mal probeweise für zweidimensionale Vektoren implementiert, das aber später aus Performancegründen nicht weiter verfolgt. Im 3D-Bereich gibt es dann allerdings zwei Arten der Multiplikation zweier Vektoren. Leider geht das Overloading der Operatoren nicht so weit, daß man dort noch nach dem Ergebnistyp unterscheidet. In dem Fall würde das Kreuzprodukt dann wohl aus der Semantik rausfallen.

Delphi-Quellcode:
const
  NativeFormat: TFormatSettings = (DecimalSeparator: '.');

type
  TVektor = record
    X, Y: Extended;
    class operator Add(A, B: TVektor): TVektor;
    class operator Divide(A: TVektor; B: Extended): TVektor;
    class operator Equal(A, B: TVektor): Boolean;
    class operator Explicit(A: TVektor): string;
    class operator Implicit(A: TVektor): string;
    class operator Multiply(A: Extended; B: TVektor): TVektor;
    class operator Multiply(A: TVektor; B: Extended): TVektor;
    class operator Multiply(A: TVektor; B: TVektor): Extended;
    class operator Negative(A: TVektor): TVektor;
    class operator NotEqual(A, B: TVektor): Boolean;
    class operator Positive(A: TVektor): TVektor;
    class operator Subtract(A, B: TVektor): TVektor;
  end;

class operator TVektor.Add(A, B: TVektor): TVektor;
begin
  result.X := A.X + B.X;
  result.Y := A.Y + B.Y;
end;

class operator TVektor.Divide(A: TVektor; B: Extended): TVektor;
begin
  result.X := A.X / B;
  result.Y := A.Y / B;
end;

class operator TVektor.Equal(A, B: TVektor): Boolean;
begin
  result := SameValue(A.X, B.X) and SameValue(A.Y, B.Y);
end;

class operator TVektor.Explicit(A: TVektor): string;
begin
  result := Format('(%1.3f, %1.3f)', [A.X, A.Y], NativeFormat);
end;

class operator TVektor.Implicit(A: TVektor): string;
begin
  result := string(A);
end;

class operator TVektor.Multiply(A: Extended; B: TVektor): TVektor;
begin
  result.X := A * B.X;
  result.Y := A * B.Y;
end;

class operator TVektor.Multiply(A: TVektor; B: Extended): TVektor;
begin
  result.X := A.X * B;
  result.Y := A.Y * B;
end;

class operator TVektor.Multiply(A, B: TVektor): Extended;
begin
  result := A.X * B.X + A.Y * B.Y;
end;

class operator TVektor.Negative(A: TVektor): TVektor;
begin
  result.X := -A.X;
  result.Y := -A.Y;
end;

class operator TVektor.NotEqual(A, B: TVektor): Boolean;
begin
  result := not SameValue(A, B);
end;

class operator TVektor.Positive(A: TVektor): TVektor;
begin
  result := A;
end;

class operator TVektor.Subtract(A, B: TVektor): TVektor;
begin
  result.X := A.X - B.X;
  result.Y := A.Y - B.Y;
end;

BUG 17. Mär 2014 14:11

AW: Vektorklasse mit echten Operatoren
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1252255)
Im 3D-Bereich gibt es dann allerdings zwei Arten der Multiplikation zweier Vektoren.

Zusätzlich zu Kreuzprodukt und Skalarprodukt gibt es noch die Elemente-weise Multiplikation, die ist je nach Anwendung auch nicht so uninteressant.

Der schöne Günther 17. Mär 2014 14:55

AW: Vektorklasse mit echten Operatoren
 
Wie sieht es eigentlich mit dem "Nextgen"-Compiler aus? Da müsste doch für Klassen mittlerweile volle Operator-Überladung funktionieren, oder?

Uwe Raabe 17. Mär 2014 15:20

AW: Vektorklasse mit echten Operatoren
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1252266)
Wie sieht es eigentlich mit dem "Nextgen"-Compiler aus? Da müsste doch für Klassen mittlerweile volle Operator-Überladung funktionieren, oder?

Was bringt dich zu der Annahme?

Namenloser 17. Mär 2014 15:42

AW: Vektorklasse mit echten Operatoren
 
Ich hatte das Kreuzprodukt mal mit dem Divisionsoperator realisiert, da dieser bei Vektoren sonst keine sinnvolle Verwendung hat.

Uwe Raabe 17. Mär 2014 15:48

AW: Vektorklasse mit echten Operatoren
 
Zitat:

Zitat von Namenloser (Beitrag 1252271)
Ich hatte das Kreuzprodukt mal mit dem Divisionsoperator realisiert, da dieser bei Vektoren sonst keine sinnvolle Verwendung hat.

Die Idee hatte ich auch schon, aber ein Hauptgrund für die Verwendung des Operatoren ist je eigentlich eine bessere Lesbarkeit.

Der schöne Günther 17. Mär 2014 15:48

AW: Vektorklasse mit echten Operatoren
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1252267)
Zitat:

Zitat von Der schöne Günther (Beitrag 1252266)
Wie sieht es eigentlich mit dem "Nextgen"-Compiler aus? Da müsste doch für Klassen mittlerweile volle Operator-Überladung funktionieren, oder?

Was bringt dich zu der Annahme?

Automatische Referenzzählung:
Delphi-Quellcode:
var
   obj1, obj2: TMyObject;
begin
   obj2 := obj1 + obj1 + obj1;
end;
Allein für die erste "Addition" entsteht ein vom Programmierer nicht referenzierbares "Zwischenobjekt". Der Programmierer kann es nicht explizit freigeben und es liegt auf Ewig unbenutzt im Speicher.

Deshalb gibt es im "alten" Delphi-Compiler keine Operator-Überladung für Klassen. Dachte ich.

Mit ARC hat man dieses Problem ja nicht.

Anscheinend habe ich sogar Recht:
Zitat:

A very interesting side effect of using ARC memory management is that the compiler can handle the lifetime of temporary objects returned by functions. One specific case is that of temporary objects returned by operators. In fact, a brand new feature of the new Delphi compiler is the ability to define operators for classes, with the same syntax and model that has been available for records since Delphi 2006.

Note: The following code example works with the Delphi mobile (iOS) compilers, but cannot be compiled by the Delphi desktop compilers.
(Quelle: Embarcadero Docwiki)


Mann, gebt mir endlich den "Nextgen"-Compiler für Windows 8-)


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:06 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz