Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Koordinatensystem und Rects (https://www.delphipraxis.net/180331-koordinatensystem-und-rects.html)

stahli 12. Mai 2014 19:22

Koordinatensystem und Rects
 
Ich habe mal eine generelle Frage:

Wenn man heute Computer (oder Delphi) neu erfinden würde, wäre es dann Eurer Meinung nach sinnvoll, Koordinatensysteme und Rects 1-basiert aufzubauen - zumindest in der Programmiersprache? Ich fände es für die Programmierer wesentlich einfacher, damit umzugehen. Der Compiler kann das ja dann 0-basiert umrechnen.

So wäre das linke obere Pixel mit 1,1 ansprechbar, so wie man es intuitiv wohl auch auf einer Skizze mit Bleistift handhaben würde.

Auch verstehe ich nicht ganz, warum ein definiertes Rect.Create(Point(1,1),5,5) nachher in Rect.Right = 6 enthält.
Im Moment bezeichnet Rect.Right nicht das letzte Pixel eines Rects sondern das rechts daneben.
Wenn man von 1 an 5 Pixel zählt liegt das letzte aber bei 5. Von 1 bis 5 sind also 5 Pixel belegt, die Breite ist 5 und das letzte (rechte) Pixel liegt bei 5 (nicht bei 6).

Irgendwie finde ich das unlogisch.

Dass es nachträglich schwer zu ändern ist, ist mir klar. Aber schließt Ihr Euch mir an, dass es grundsätzlich besser anders gelöst hätte werden sollen?


Delphi-Quellcode:
{ TRect }

class function TRect.Empty: TRect;
begin
  Result := TRect.Create(0,0,0,0);
end;

constructor TRect.Create(const Origin: TPoint);
begin
  Create(Origin.X, Origin.Y, Origin.X, Origin.Y);
end;

constructor TRect.Create(const Origin: TPoint; Width, Height: Integer);
begin
  Create(Origin.X, Origin.Y, Origin.X + Width, Origin.Y + Height);
end;

constructor TRect.Create(const Left, Top, Right, Bottom: Integer);
begin
  Self.Left := Left;
  Self.Top  := Top;
  Self.Right := Right;
  Self.Bottom:= Bottom;
end;

SMO 12. Mai 2014 20:02

AW: Koordinatensystem und Rects
 
Fände ich nicht sinnvoll. Und gerade Programmierer sollten doch gewöhnt sein, beim Zählen mit 0 anzufangen und nicht mit 1. ;)

Ich würde das linke, obere Pixel nie "intuitiv" mit 1,1 bezeichnen. Im Matheunterricht war der Ursprung von Graphen ja auch bei 0,0 und nicht 1,1.
Ich denke, das ist einfach Gewohnheitssache.

Die Right und Bottom Werte sind auch nicht schwer zu verstehen. Sie sind eben "exklusive", wenn man das weiß sollte es keine Probleme geben.
D.h. ein Rect(1, 2, 6, 6) auf Pixel bezogen wäre 5 breit (Right - Left) und 4 hoch (Bottom - Top), wobei Pixelzeile 6 und Pixelspalte 6 nicht benutzt werden.
Wollte man Right und Bottom "inklusive", dann müsste man zum Bestimmen der Breite und Höhe immer +1 machen (Right - Left + 1). Das ist nicht praktischer.
Windows handhabt die Rects übrigens genauso, so weit ich weiß, auch ein Grund kein anderes System zu erfinden.

Namenloser 12. Mai 2014 20:43

AW: Koordinatensystem und Rects
 
Ich sehe es eher umgekehrt, man sollte sich in Teilen der Mathematik und im Alltag abgewöhnen, bei 1 anzufangen zu zählen (ich meine das natürlich nur halb ernst, es ist in unseren Köpfen und der Sprache zu etabliert um es zu ändern). In der Algorithmenvorlesung wurden hier z.B. aus irgendwelchen Gründen Heaps mit 1-basierten Arrays gezeigt. Mit 0-basierten Arrays wären die Formeln im allgemeinen viel kürzer gewesen... und das ist nicht selten so. Eigentlich ist es willkürlich bei 1 anzufangen, bei 0 erscheint es mir logischer.

Der einzige Vorteil, wenn man bei 1 anfängt zu zählen, ist, dass der Index vom letzten Element = die Anzahl der Elemente ist. Aber das ist in der Praxis, finde ich, nicht so ein großer Vorteil und dafür hat man Nachteile, die überwiegen.

Und was im eindimensionalen gilt, gilt im mehrdimensionalen erst recht. Wie SMO schon schrieb, würde auch ich schon rein intuitiv nie das obere linke Pixel mit (1,1) bezeichnen, sondern immer mit (0,0).

Aber abgesehen davon wäre vieles tatsächlich umständlicher mit einem Ursprung in (1,1). Bei Grafikschnittstellen, die über die Fähigkeiten der GDI herausgehen, ist es etwa üblich, wenn man z.B. ein Objekt gedreht oder an einen anderen Ort zeichnen möchte, das Koordinatensystem zu transformieren. Man könnte sich als Beispiel das Zeichnen eines Buttons vorstellen. Dazu schreibt man sich eine Routine, die einen Button immer achsenparallel in den Bereich zwischen (0.0, 0.0) und (1.0, 1.0) zeichnet (wobei die Koordinaten aber relativ sind). Wenn man jetzt einen Button mit den Ausmaßen 50*20 zeichnen will, dann setzt man vor dem Aufruf der Routine einfach eine Transformationsmatrix, die alle Y-Koordinaten um den Faktor 20 und alle X-Koordinaten um den Faktor 50 streckt. Und wenn man den Button woanders als in den Ursprung zeichnen will, dann setzt man eine Transformationsmatrix, die zu X und Y jeweils einen bestimmten Wert addiert, etc. – so kann man auch Drehungen, Spiegelungen und Kombinationen aus allem umsetzen. Zurück zu unserem Button: Wenn die Routine von (0,0) als Ursprung ausgeht, ist das alles ziemlich einfach – wenn man dagegen von (1.0, 1.0) nach (2.0, 2.0) gezeichnet hätte, würde auch der „Offset“ mitgestreckt und man müsste dann wieder was abziehen etc., und falls die Routine wiederum eine verschachtelte Zeichenroutine aufruft, dann würde mit jeder Rekursionsebene der Ursprung eins weiter nach unten rechts rücken, und man müsste vor jedem Funktionsaufruf daran denken, ihn erst eins nach links oben zu verschieben, damit es sich wieder aufhebt etc., mit anderen Worten, es wäre ein totaler Rückschritt.

Perlsau 12. Mai 2014 21:22

AW: Koordinatensystem und Rects
 
Zitat:

Zitat von Namenloser (Beitrag 1258646)
Ich sehe es eher umgekehrt, man sollte sich in Teilen der Mathematik und im Alltag abgewöhnen, bei 1 anzufangen zu zählen (ich meine das natürlich nur halb ernst, es ist in unseren Köpfen und der Sprache zu etabliert um es zu ändern). In der Algorithmenvorlesung wurden hier z.B. aus irgendwelchen Gründen Heaps mit 1-basierten Arrays gezeigt. Mit 0-basierten Arrays wären die Formeln im allgemeinen viel kürzer gewesen... und das ist nicht selten so. Eigentlich ist es willkürlich bei 1 anzufangen, bei 0 erscheint es mir logischer.

Zähler <> Index

Was ich damit sagen möchte: Es ist korrekt, beim Zählen einer Menge mit 1 zu beginnen, weil man als Ergebnis ja die Anzahl der zu zählenden Einheiten haben möchte. Deshalb ist der Wert des letzten Index z.B. einer TStringList niemals identisch mit dem Wert seines Count-Properties. Anders ausgedrückt: Der Index hat nichts mit der Anzahl zu tun.

Namenloser 12. Mai 2014 22:17

AW: Koordinatensystem und Rects
 
Zitat:

Zitat von Perlsau (Beitrag 1258653)
Anders ausgedrückt: Der Index hat nichts mit der Anzahl zu tun.

Ja eben darum geht es mir doch. Natürlich habe ich nicht eine Anzahl von 0 Äpfeln im Korb, wenn ich einen Apfel darin habe, aber dieser ist dann eben Apfel 0 oder der 0. Apfel (letzteres ist halt sprachlich nur verwirrend, vor allem weil der nächste dann der „erste“ Apfel wäre).

Perlsau 12. Mai 2014 22:27

AW: Koordinatensystem und Rects
 
Du hattest aber doch geschrieben:

Zitat:

Zitat von Namenloser (Beitrag 1258646)
Ich sehe es eher umgekehrt, man sollte sich in Teilen der Mathematik und im Alltag abgewöhnen, bei 1 anzufangen zu zählen (ich meine das natürlich nur halb ernst, es ist in unseren Köpfen und der Sprache zu etabliert um es zu ändern).

Diese Forderung beruht auf einer Verwechslung: Du verwechselst hier Anzahl mit Index, indem du forderst, man solle beim Zählen ebenfalls mit 0 statt mit 1 beginnen. Beim Index geht es aber nicht um's Zählen, sondern um's Kennzeichnen. Wie kannst du nun behaupten, es ginge dir darum, daß der Index nichts mit der Anzahl zu tun habe?

Es gibt gute Gründe dafür, daß ein Index in der Informatik bei 0 und nicht bei 1 beginnt. Ein Byte kann 256 verschiedene Werte aufnehmen, von 0 bis 255, binär dargestellt von 00000000 bis 11111111. Muß ich noch weiter ausholen?

Was auch gerne zu Verwechslungen führt, ist die Angabe eines Bereiches, beispielsweise von 7 bis 14. Ist das inklusive, so ergeben sich nicht, wie man oberflächlich betrachtet schnell vermuten würde, 14 - 7 = 7 Einheiten, sondern 8 Einheiten, weil die 7 bereits mitgezählt wird. Ungeübte Rechner und Laien fallen da sehr oft rein. Man muß aber nicht alles versimplifizieren, nur um "Analphabeten das Lesen lernen" zu erleichtern.

Bjoerk 12. Mai 2014 22:30

AW: Koordinatensystem und Rects
 
Fände ich grundsätzlich sinnvoll. Erinnern wir uns an unser erstes array. Haben wir das 0..N-1 deklariert? Wohl kaum?

Edit: Würde ebenfalls auch eine SetLengthEx(AItems, ALow, AHigh) begrüßen.Schließlich kann man das bei statischen Arrays ja auch.

Namenloser 12. Mai 2014 22:42

AW: Koordinatensystem und Rects
 
Zitat:

Zitat von Perlsau (Beitrag 1258669)
Du hattest aber doch geschrieben:

Zitat:

Zitat von Namenloser (Beitrag 1258646)
Ich sehe es eher umgekehrt, man sollte sich in Teilen der Mathematik und im Alltag abgewöhnen, bei 1 anzufangen zu zählen (ich meine das natürlich nur halb ernst, es ist in unseren Köpfen und der Sprache zu etabliert um es zu ändern).

Diese Forderung beruht auf einer Verwechslung: Du verwechselst hier Anzahl mit Index, indem du forderst, man solle beim Zählen ebenfalls mit 0 statt mit 1 beginnen. Beim Index geht es aber nicht um's Zählen, sondern um's Kennzeichnen. Wie kannst du nun behaupten, es ginge dir darum, daß der Index nichts mit der Anzahl zu tun habe?

Es geht hier um Zählen im Sinne von Aufzählen oder Durchzählen. Und dass man beim „Zählen“ wie du es meinst, bei 1 beginnen würde, ist außerdem eine falsche Annahme deinerseits. Vor der Anzahl 1 kommt schließlich die Anzahl 0, nämlich wenn man gar keine Elemente hat. Also kann man nicht sagen, dass man bei 1 anfängt zu zählen.
Zitat:

Zitat von Perlsau (Beitrag 1258669)
Es gibt gute Gründe dafür, daß ein Index in der Informatik bei 0 und nicht bei 1 beginnt. Ein Byte kann 256 verschiedene Werte aufnehmen, von 0 bis 255, binär dargestellt von 00000000 bis 11111111. Muß ich noch weiter ausholen?

Ohweia besser nicht, sonst kommt gleich noch der Kryptochef...

BUG 12. Mai 2014 22:59

AW: Koordinatensystem und Rects
 
Insgesamt finde ich nullbasierte Indices sinnvoll, da es viele Berechnungen erleichtert.
Seien es nun Adressberechnungen (Offset + Index*Stride) oder Transformationen in Vektorräumen.

Wenn man unbedingt eine Eselsbrücke braucht: Man kann sich die Indices als zwischen den Elementen liegend vorstellen.
Code:
Index--- 0>1>2>3>4>5
Speicher |H|a|l|l|o|

Bezüglich der Grafik @stahli: Wenn dich das so stört, dann schreib dir halt eine Funktion, die zwischen deinem favorisierten Koordinatensystem und dem Nativen übersetzt.

stahli 12. Mai 2014 23:32

AW: Koordinatensystem und Rects
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich sehe das Problem halt immer noch aus Anfängersicht ;-)


@Namenloser

Ja, das ist verständlich und plausibel. Allerdings würde ich noch zwischen einem mathematischen Koordinatensystem und dem Canvas (oder Bitmap) unterscheiden.

Der Canvas enthält ja ganze Pixel bzw. Kästchen. Das Kästchen links oben ist bereits komplett zu sehen. Wenn der Nullpunkt der Mittelpunkt des ersten Pixels wäre dürfte dieses nur zu einem Viertel zu sehen sein. Wenn man Pixel[0,0] anspricht, erhält man aber das gesamte Pixel, das auf dem Bildschirm zu sehen ist.

Also Deine Anmerkungen kann ich nachvollziehen für
- Formelberechnungen in einem Koordinatensystem
und
- 3D-Grafiken.

Für 2D-Grafiken sehe ich das noch etwas anders.
Wenn man eine Grafik scaliert kann (und muss) man dazu auf ein 0-basiertes Koordinatensystem zurück greifen.
Für einen einfachen Zugriff auf ein fertiges Bitmap finde ich das wieder nicht sinnvoll.
Letztlich müsste ja nur der Pascal-Interpreter eine 1,1-Basis "vortäuschen" während der Compiler intern mit 0,0 rechnet.
An anderen Stellen vereinfacht der Compiler ja auch Zugriffe auf Daten, die intern komplexer verwaltet werden.

Wenn das Koordinatensystem nicht zwischen den Pixeln sitzen würde, wären Rect.Width und Rect.Right m.E. eindeutiger.
Man kann sich ja den Canvas als Schachbrett vorstellen. Da bezieht man sich ja auch auf die Kästchen und nicht auf die Trennlinien dazwischen.

Dass die Speicherverwaltung (z.B. einer TList) selbst von einem Offset 0-basiert ist, ist auch wieder klar. Das muss ja aber nicht in der Programmiersprache abgebildet werden (wie z.B. String[1] wäre auch List[1] realisierbar gewesen).


@Bug

Klar kann ich mir eine entsprechende Funktion schreiben, ich wollte aber gern mal die grundsätzlichen Meinungen dazu hören.
Man könnte ja generell auch in einer Programmiersprache (z.B. Pascal) entsprechende Regelungen einbauen, die für die Neulinge logischer sind.
Wer sich dann um komplexere mathematische Berechnungen oder z.B. 3D-Grafik kümmern muss oder will könnte auf 0-basierte Berechnungen umrechnen.
Anfänger wären dankbar und Profis hätten keine wirklichen Nachteile.



Ok, ich sehe ein, dass es für einige Belange schon sinnvoll ist.
Für höhere Programmiersprachen hätte man das aber auch wieder vereinfachen können.
Ich hätte das so geregelt und der Programmierer könnte ja bei Bedarf immer noch 1 subtrahieren - wenn notwendig.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:00 Uhr.
Seite 1 von 2  1 2      

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