Es ist nicht so, dass dies keinen Sinn ergibt, aber es funktioniert in 99% der Fälle nur umständlich.
In 2D-Grafiken werden Rechtecke häufig als Punktpaar initialisiert, gespeichert und bearbeitet. In keiner bestimmten Sprache,
class Rect:
p1, p2: point
Es ist sinnvoller, ein Rechteck wie folgt als zwei x-Werte und zwei y-Werte zu definieren:
class Rect
xleft, xright: int
ytop, ybottom: int
Mit zwei Punkten müsste man, wenn man irgendwo im Quellcode den y-Wert von oben verwenden möchte, rect.p1.y sagen (hmmm, halt und denk, ist es p1 oder p2), aber Mit den vier Werten als einfache Datenelemente ist es klar und direkt: rect.ytop (kein Denken erforderlich!) Die Verwendung von zwei Punkten bedeutet, dass Sie beim Umgang mit der Vertikalen die Horizontale verwickeln müssen. Es gibt eine irrelevante Beziehung zwischen unabhängigen Elementen.
Wie ist diese Zwei-Punkte-Idee entstanden und warum bleibt sie bestehen? Hat es Vorteile gegenüber bloßen x- und y-Koordinaten?
HINZUGEFÜGTER HINWEIS: Diese Frage bezieht sich auf XY-ausgerichtete Rechtecke, z. B. in Windows-Managern und GUI-Toolkits, und nicht auf beliebige Formen in der Zeichen- und Mal-App.
quelle
Antworten:
Haben Sie gedacht, dass es weniger fehleranfällig ist?
Wenn Sie (Point1, Point2) verwenden, ist es sehr klar, was Sie angeben . Wenn Sie 2 Punkte angeben, ist der einzige mögliche Fehler, dass der Benutzer beim Konstruieren der Punkte das x und das y vertauscht hat, da die Reihenfolge der Punkte keine Rolle spielt.
Wenn Sie 4 Ganzzahlen angeben, kann jemand, der nicht aufpasst, (x1, x2, y1, y2) angeben, wann Sie möchten (x1, y1, x2, y2) oder umgekehrt. Einige APIs wie die Rect- Struktur von WCF definieren ein Rechteck als (x, y, width, height), was dann zu Verwirrung darüber führen kann, was (1, 2, 3, 4) bedeutet. Ist das (x, y, w, h) oder (x1, y1, x2, y2) oder (x1, x2, y1, y2)?
Alles in allem scheint mir (Punkt 1, Punkt 2) ein bisschen sicherer zu sein.
quelle
Ich habe es immer gemocht, ein Rechteck als Punkt + Breite und Höhe zu definieren, wobei der Punkt die linke obere Ecke des Rechtecks ist.
Fügen Sie dann die Methoden hinzu, die Sie zum Abrufen der anderen Metriken benötigen. Wie die Java- Version
quelle
Tatsächlich wird ein Rechteck nicht durch 2 Punkte definiert. Ein Rechteck kann nur durch zwei Punkte definiert werden, wenn es parallel zu den Achsen ist.
Es gibt verschiedene Möglichkeiten, Rechtecke darzustellen, die parallel zu den Achsen sind:
Für (1) verwenden viele Bibliotheken eine Konvention, um zu bestimmen, welche zwei Punkte verwendet werden - beispielsweise topLeft und bottomRight.
Die Wahl der Darstellung mag vom ursprünglichen Zweck der Rechteckdefinition abhängen, aber ich stelle mir vor, dass dies oft willkürlich ist . Die Darstellungen entsprechen den Informationen, die sie enthalten. Sie unterscheiden sich jedoch in der Leichtigkeit, mit der Eigenschaften des Rechtecks berechnet werden können, und in der Bequemlichkeit, mit der Operationen am Rechteck ausgeführt werden können.
Vorteile der Definition (1) gegenüber anderen sind:
quelle
Na ja,
p1: Point
undp2: Point
haben die beidenint
sowieso jeweils zwei Koordinaten ? Ist Ihre Klasse also nicht dasselbe?Und wenn Sie diese beiden Punkte als erstklassige
Point
Objekte speichern , können Sie sie dann nicht noch nützlicher nutzen? In den meisten mir bekannten grafischen Koordinatensystemen werden Punkte auf diese Weise in Unterklassen unterteilt, um eine Hierarchie von Objekten zu erstellenpoint -> circle -> ellipse
.Wenn Sie also ein Objekt erstellen, das die
Point
Klasse nicht verwendet , haben Sie dieses Objekt vom Rest der Klassenhierarchie getrennt.quelle
ytop
/ybottom
-Ansatz müsste es jedoch auch eine Garantie geben,ybottom
die tatsächlich darunter liegtytop
.Deshalb mag ich Delphi's
TRect
. Es ist definiert als ein Variantendatensatz (Union-Struktur in C-Speak), der entweder als TopLeft- und BottomRight-Punkt oder als Ganzzahl von Top, Left, Bottom und Right interpretiert werden kann, je nachdem, was momentan praktischer ist.quelle
Sicherlich, wenn Sie Ihr Rechteck wie folgt definieren:
dann wissen Sie sofort, welcher Punkt welcher ist.
Noch besser wäre es, zusätzliche Eigenschaften hinzuzufügen, mit denen Sie das Rechteck so bearbeiten können, wie Sie es für Ihre Anwendung benötigen. Diese würden einfach die zugrunde liegende Datenstruktur aktualisieren.
Indem Sie der Form eine Transformation hinzufügen, können Sie Ihr Rechteck so ausrichten, wie Sie möchten. Sie benötigen noch einen achsenausgerichteten Begrenzungsrahmen für schnelle Annahme- / Ablehnungsprüfungen :)
Wenn Ihr Modell jedoch Rechtecke in beliebiger Ausrichtung ohne Transformation zulässt, haben "unten links" und "oben rechts" keine Bedeutung, was zu "p1" und "p2" (oder etwas Äquivalentem) führt.
quelle
Ich halte es für sinnvoller, wenn ein Rechteck durch eine x- und eine y-Ausdehnung und einen Punkt dargestellt wird. Sie können den Positionspunkt sogar zur Mitte des Rechtecks machen, damit er unabhängig von der Drehung ist
aber es war wahrscheinlich am einfachsten, es als zwei Punkte zu codieren!
quelle
Ich mag es nicht, weil wir einen potenziellen Freiheitsgrad ausgeschöpft haben, der im Wesentlichen eine willkürliche Rotation zulässt. Ein allgemeines 2D-Rechteck hat fünf Unbekannte (Freiheitsgrade). Wir könnten sie als die Koordinaten eines Punktes, die Längen der beiden Seiten, die mit diesem Punkt einen Scheitelpunkt bilden, und den Winkel von der Horizontalen der ersten Linie angeben (die andere wird mit einem um 90 Grad größeren Winkel angenommen). Eine unendliche Anzahl anderer Möglichkeiten könnte ebenfalls verwendet werden, es gibt jedoch fünf unabhängige Größen, die spezifiziert werden müssen. Einige Entscheidungen führen zu einer einfacheren Algebra als andere, je nachdem, was mit ihnen gemacht wird.
quelle
Ist das nicht genau dasselbe wie 2 Punkte? Wie ist das umständlich ... die meisten Zeichenroutinen erfordern Punkte, keine separaten x / y-Komponenten.
quelle
Wenn Sie Rechtecke als Punktpaare definieren, können Sie den Punkt als Scheitelpunkt für eine andere Form wiederverwenden. Nur ein Gedanke...
quelle
Ich glaube, es geht hauptsächlich darum, Gleichförmigkeit zwischen allen Formprimitiven herzustellen.
Natürlich können Sie Rechtecke auf viele verschiedene Arten definieren, aber wie definieren Sie ein Dreieck, einen Stern oder einen Kreis so, dass ähnliche Datenstrukturen verwendet werden können?
Alle Polygone können durch ihre Punkte definiert werden, wobei eine kurze Logik benötigt wird, um zu bestimmen, was mit den Punkten geschehen soll.
Grafikbibliotheken bearbeiten diese Polygone in erster Linie in Bezug auf Eckpunkte und Kanten, sodass Punkte und die Linien zwischen ihnen bei allen Berechnungen auf diese beiden Features angewendet werden, also auf das und die Facetten, aber das ist nur eine Funktion der Kanten.
quelle
In zwei Dimensionen ist das Speichern eines Rechtecks als zwei Punkte klarer als das Definieren einer bestimmten Ecke und einer Breite und Höhe. Berücksichtigen Sie negative Breite oder Höhe oder die Berechnungen, die erforderlich sind, um die einzelnen Optionen voneinander zu bestimmen.
Das Durchführen von Rotationen auf einem durch Punkte definierten Rechteck ist auch viel einfacher als bei einem Punkt plus Breite und Höhe.
Ich würde erwarten, dass die Verkapselung diese Unterscheidung als Benutzer der Klasse unwichtig macht.
Ein Rechteck sollte aus drei Punkten bestehen, die in drei Dimensionen gut definiert sind. Ich bin mir nicht ganz sicher, ob ein Rechteck in vier oder mehr Dimensionen definiert werden muss.
quelle
Es ist völlig willkürlich. Sie benötigen vier Informationen, um ein Rechteck zu zeichnen. Die Bibliotheksdesigner haben beschlossen, es mit zwei Punkten (jeweils mit einer xy-Koordinate) darzustellen, hätten es aber auch problemlos mit x / y / w / h oder oben / unten / links / rechts tun können.
Ich nehme an, die eigentliche Frage des OP lautet: Warum wurde diese besondere Wahl getroffen?
quelle
Die Auswahl der Parameter ist nur für die Designer / Programmierer auf niedriger Ebene wichtig.
Hochrangige Benutzer müssen nur über Folgendes nachdenken:
Hinweis: Um den Genauigkeitsverlust während der Skalierungstransformation zu minimieren, ist es manchmal angebracht, eine zweite Rect-Klasse zu implementieren, die Gleitkommakoordinaten verwendet, damit Zwischenergebnisse in einer Folge von Transformationen genau gespeichert und in der nur auf ganze Zahlen gerundet werden können letzter Schritt.
quelle
Wie @Steven sagt, sollte es sich um einen (x, y) Punkt und einen (w, h) Größenvektor handeln. Das ist, weil es leicht ist, in eine Mehrdeutigkeit zu geraten. Angenommen, Sie haben das folgende ausgefüllte Rechteck ab Punkt (0,0).
Klar ist es Breite, Höhe sind (3,3), aber was ist der zweite Punkt? Ist es (2,2) oder (3,3)?
Diese Mehrdeutigkeit kann alle Arten von Problemen verursachen.
Ich habe gelernt , vor den harten Weg Jahren , dass es besser ist , von grafischen Koordinaten wie die Linien zu denken , zwischen den Pixeln, nicht wie die Linien sind die Pixel auf . Auf diese Weise gibt es keine Mehrdeutigkeit.
quelle
Wir können sowohl Pb als auch Pc folgendermaßen definieren:
und
Aus Symmetriegründen müssen also nicht alle vier Punkte definiert werden
quelle