Frage

Es ist nicht so, dass dies nicht sinnvoll, aber es funktioniert einfach out umständlich 99% der Zeit.

Oft in 2D-Grafik Rechtecke initialisiert sind, gespeichert und manipuliert als ein paar Punkte.In keiner Sprache,

class Rect:
   p1, p2: point

Es macht mehr Sinn, ein Rechteck zu definieren, wie zwei x-Werte und zwei y-Werte, wie diese:

class Rect
   xleft, xright: int
   ytop, ybottom: int

Mit zwei Punkten, wenn an irgendeinem Ort in der source-code, den Sie verwenden möchten, der y-Wert des oberen, Sie würde sagen, rect.p1.y (hmmm, stoppen Sie und denken, ist es p1 oder p2), aber mit vier Werte als reinen Daten-member, es ist klar und direkt:rect.ytop (kein denken erforderlich!) Die Verwendung von zwei Punkten bedeutet, dass im Umgang mit der vertikalen, Sie zu verwirren die horizontale;es gibt eine überflüssige Beziehung zwischen indepenent Elemente.

Wie hat dieser zwei-Punkt-Idee zustande kommen und warum es Auftritt?Tut es haben einige Vorteile über die nackten x-und y-Koordinaten?

HINWEIS HINZUGEFÜGT:Diese Frage ist im Kontext der X-Y ausgerichtet Rechtecke, wie in der windows-Manager und GUI-toolkits, die nicht im Zusammenhang mit beliebigen Formen in der Zeichnung und Malerei app.

War es hilfreich?

Lösung

Haben Sie nachgedacht, dass es weniger fehleranfällig ist?

Wenn Sie (Punkt1, Punkt2) verwenden, ist dies dann sehr klar, was Sie angeben. Wenn Sie 2 Punkte angeben, besteht der einzig mögliche Fehler darin, dass der Benutzer seine X und Y beim Erstellen der Punkte als die Reihenfolge der Punkte nicht durchmischt hat.

Wenn Sie 4 Ganzzahlen liefern, dann kann er, wenn jemand nicht aufpasst, (x1, x2, y1, y2) nicht liefern, wenn Sie möchten (x1, y1, x2, y2) oder umgekehrt. Auch einige APIs wie WCFs Rechte Struktur definieren ein Rechteck als (x, y, breite, Höhe), das dann Verwirrung darüber verursachen 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 (Punkt1, Punkt2) etwas sicherer zu sein.

Andere Tipps

Ich habe mir immer gewünscht, definieren Sie ein Rechteck, wie ein Punkt, + Breite und-Höhe, in der der Punkt in der oberen linken Ecke des Rechtecks.

class Rect {
  float x, y;
  float width, height;
}

Und dann hinzufügen, was auch immer Methoden, die Sie brauchen, Holen sich die anderen Metriken.Wie die Java version

Eigentlich ein rectagle ist nicht definiert durch 2 Punkte.Ein Rechteck kann nur durch zwei Punkte definiert, wenn es parallel zu den Achsen.

Es gibt mehrere Möglichkeiten, um zu repräsentieren die Rechtecke, die parallel zu den Achsen:

  1. Zwei Diagonal gegenüberliegende Punkte
  2. Ein Eckpunkt, Höhe und Breite
  3. Centre point, halbe Höhe und Breite von (selten, aber manchmal nützlich).
  4. Als zwei X-Koordinaten und der beiden Y-Koordinaten

Zu (1) viele Bibliotheken verwenden Sie eine Konvention, um zu bestimmen, welche zwei Punkte verwendet werden - topLeft und bottomRight, zum Beispiel.

Die Wahl der Repräsentation angetrieben werden kann, indem der ursprüngliche Zweck der Rechteck-definition, aber ich kann mir vorstellen, dass es Häufig willkürliche.Die Darstellungen sind gleichwertig in den Informationen, die Sie in sich tragen.Sie tun, unterscheiden sich jedoch in der Leichtigkeit, mit der die Eigenschaften des Rechtecks berechnet werden kann und die den Komfort bei welchen Operationen können durchgeführt werden auf die reectangle.

Vorteile der definition (1) über gehören unter anderem:

  • Die Konsistenz der API mit anderen Polygonen, Linien etc.
  • topLeft, bottomRight übergeben werden kann, um jede Methode, die akzeptiert Punkte
  • Methoden der Point-Klasse aufgerufen werden kann, auf topLeft, bottomRight
  • Die meisten Eigenschaften abgeleitet werden kann leicht, wie zB.bottomLeft, topRight, Breite, Höhe, Zentrum, Diagonale, etc.

Brunnen p1: Point und p2: Point werden jeweils haben zwei int Koordinaten Wie auch immer, beträgt Ihr Unterricht nicht dasselbe?

Und wenn Sie diese beiden Punkte als erstklassig speichern Point Objekte, bekommen Sie nicht etwas mehr Nützlichkeit von ihnen? In den meisten grafischen Koordinatensystemen, von denen ich kenne, werden Punkte auf diese Weise unterklassifiziert, um eine Hierarchie von Objekten zu erstellen: point -> circle -> ellipse usw.

Wenn Sie also ein Objekt erstellen, das das nicht verwendet Point Klasse, Sie haben dieses Objekt vom Rest der Klassenhierarchie geschieden.

Deshalb mag ich Delphi's TRect. Es ist definiert als eine Variante (Union Struct in C-Speak), die entweder als Topleft und als unterer Punkt oder obere, linke, untere und rechte ganze Zahlen interpretiert werden kann, je nachdem, was im Moment bequemer ist.

Sicherlich, wenn Sie Ihr Rechteck definieren wie:

class Rect
{
    Point bottomLeft;
    Point topRight;
}

Dann wissen Sie sofort, welcher Punkt welcher ist.

Noch besser wäre es, zusätzliche Eigenschaften hinzuzufügen, die es Ihnen ermöglichten, das Rechteck zu manipulieren, auf welche Weise Sie für Ihre Anwendung benötigt werden. Diese würden einfach die zugrunde liegende Datenstruktur aktualisieren.

Durch Hinzufügen einer Transformation zu der Form können Sie Ihr Rechteck auf eine Weise orientieren, die Sie möchten. Sie würden immer noch eine Achse ausgerichtete Begrenzungsbox benötigen, um Überprüfungen zu akzeptieren/abzulehnen :)

Wenn Ihr Modell jedoch Rechtecke in einer Orientierung erlaubt, ohne eine Transformation anzuwenden, haben "unten links" und "oben rechts" keine Bedeutung, was zu "P1" und "P2" (oder etwas Äquivalent) zurückführt.

ich denke, es macht mehr Sinn, sich für ein Rechteck dargestellt werden, die durch eine x-und y-Umfang und einen Punkt;Sie könnten sogar die Position der Mitte des Rechtecks, so würde es unabhängig von rotation

aber es war wahrscheinlich am einfachsten code, der es zwei Punkte!

Ich mag es nicht, weil wir ein potenzielles Freiheitsgrad ausgelöst haben, was im Wesentlichen eine willkürliche Rotation ermöglicht. Ein allgemeines 2D -Rechteck hat fünf Unbekannte (Freiheitsgrade). Wir könnten sie als Koordinaten eines Punktes, die Längen der beiden Seiten angeben, die mit diesem Punkt einen Scheitelpunkt bilden, und der Winkel von der Horizontalen der ersten Zeile (der andere wird angenommen, dass er einen Winkel von 90 Grad mehr hat). Eine unendliche Anzahl anderer Möglichkeiten könnte ebenfalls verwendet werden, aber es gibt fünf unabhängige Mengen, die angegeben werden müssen. Einige Auswahlmöglichkeiten führen zu einer einfacheren Algebra als andere, je nachdem, was mit ihnen getan wird.

Ist das nicht genau das Gleiche wie 2 Punkte? Wie ist das umständlich ... die meisten Zeichenroutinen erfordern Punkte, nicht separate X/Y -Komponenten.

Wenn Sie Rechtecke als Punktpaare definieren, können Sie den Punkt als Scheitelpunkt für eine andere Form wiederverwenden. Nur ein Gedanke...

Ich glaube, es ist hauptsächlich, ein Gleichmäßigkeit zwischen allen Formprimitiven zu etablieren.

Natürlich können Sie Rechteck auf viele verschiedene Arten definieren, aber wie definieren Sie ein Dreieck, einen Stern oder einen Kreis auf eine Weise, die ähnliche Datenstrukturen verwenden kann?

Alle Polygone können durch ihre Punkte definiert werden, mit einer kurzen Menge an Logik, um zu bestimmen, was mit den Punkten zu tun ist.

Grafikbibliotheken arbeiten hauptsächlich auf diesen Polygonen in Bezug auf Eckpunkte und Kanten, so dass Punkte und die Linien zwischen ihnen alle Berechnungen an diesen beiden Merkmalen funktionieren, gut, dass und Facetten, aber das selbst ist nur eine Funktion der Kanten.

In zwei Dimensionen, die Speicherung eines Rechtecks als zwei Punkte ist klarer als die Definition einer bestimmten Ecke und eine Breite und Höhe von - betrachten negativer Breite oder Höhe, oder mit den Berechnungen erforderlich, um zu bestimmen, jede option, sich von den anderen.

Durchführen von Drehungen um ein Rechteck, definiert durch die Punkte ist auch viel einfacher als man definiert mit einem Punkt plus Breite und Höhe.

Ich würde erwarten, dass die Kapselung, um diese Unterscheidung auch unwichtig, da ein Benutzer der Klasse.

Ein Rechteck definiert werden sollte, da drei Punkte definiert werden in 3 Dimensionen.Ich bin mir nicht ganz sicher, die Voraussetzung für die Definition eines Rechtecks in 4 oder mehr Dimensionen.

Es ist völlig willkürlich. Sie benötigen vier Informationen, um ein Rechteck zu zeichnen. Die Bibliotheksdesigner entschieden sich, es mit zwei Punkten (jeweils mit einer XY -Koordinate) darzustellen, hätte es jedoch leicht 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 bestimmte Wahl getroffen?

Die Wahl der Parameter ist nur für die Designer / Codierer auf niedriger Ebene wichtig.

Nutzer auf hoher Ebene müssen nur darüber nachdenken:

  • IspointinRect
  • Bereich
  • Kreuzung (oder Clipping)
  • HaSoverlap (gleiche wie intersection.area> 0)
  • Union (wird eine Liste von Rechtecken)
  • Subtraktion (eine Liste von Rechtecken, die den gleichen Punktsatz darstellen, der in rect a ist, aber nicht in rect b)
  • Verwandeln
    • Verschiebungen in x und y
    • Rotation (0, 90, 180, 270)
    • Skalierung in x und y (siehe Anmerkung)
  • Einfache Syntax für Eigenschaften Xmin, Xmax, Ymin, Ymax, Breite, Höhe, so dass der Benutzer die genaue Auswahl der Parameter nicht kennen muss.

HINWEIS: Um den Präzisionsverlust während der Skalierungstransformation zu minimieren, ist es manchmal angemessen, eine zweite Rechteklasse zu implementieren, die Floating-Punkt-Koordinaten verwendet letzter Schritt.

Wie @Steven sagt, denke ich, dass es in Bezug auf einen (x, y) Punkt und einen (W, H) -Gröglichenvektor sein sollte. Das liegt daran, dass es leicht ist, in eine Unklarheit zu geraten. Angenommen, Sie haben das folgende ausgefüllte Rechteck, beginnend am Punkt (0,0).

  012
0 XXX
1 XXX
2 XXX

Offensichtlich ist es Breite, Höhe sind (3,3), aber was ist es der zweite Punkt? Ist es (2,2) oder (3,3)?

Diese Mehrdeutigkeit kann alle möglichen Probleme verursachen.

Ich habe vor Jahren auf die harte Tour gelernt, dass es besser ist, Grafikkoordinaten als die Linien zu betrachten zwischen Die Pixel, nicht als Linien, die die Pixel sind an. Auf diese Weise gibt es keine Unklarheit.

Pa(x,y)*-----------------------------------*Pb(x,y)
       |                                   |
       |                                   |
       |                                   |
       |                                   |
       |                                   |
       |                                   |
Pc(x,y)*-----------------------------------*Pd(x,y)

Wir können sowohl PB als auch PC definieren:

Pb (Pd (x), Pa (y))

und

PC (pa (x), pd (y))

Es ist also nicht erforderlich, alle vier Punkte aufgrund von Symmetrie zu definieren

Lizenziert unter: CC-BY-SA mit Zuschreibung
scroll top