Was macht man mit solch einer Fehlermeldung?



  • @zeropage sagte in Was macht man mit solch einer Fehlermeldung?:

    Rect() = default;

    Was für ein Rechteck mit ohne Ecken mag das wohl sein.



  • Gut, auch wenn ich den Scherz nicht zur Gänze verstanden habe, dieser Default-Konstruktor scheint zumindest tatsächlich überflüssig zu sein.



  • Wieso denn ein vector? Das scheint mir nicht sinnvoll zu sein.



  • Hm, was wäre denn besser? Ist ja nocht temporär.

    Wenn ich das Rect tranformieren will, benötige ich doch die Points?


  • Gesperrt

    width und height finde ich bei Rechtecken wesentlich als Rückgabewert von Methoden. Usw.

    Überelegenswert fände ich auch, ob per Template Argument z.B. festgelegt werden können soll, ob das Koordinatensystem z.B. nach y Richtung top oder Richtung bottom geht 🌝

    Edit: Ausser es wird nicht gebraucht. Aber sonst ist ja die Wiederverwendbarkeit einer Funktion ein Zweck seiner ihrer Existenz. Das vermindert die Schreibmühen. Anstatt die gesamte Berechnung jeweils hinzuschreiben, ist es dann möglich einfach z.B. Width() zu schreiben und sich nicht nochmals um das Tippen und Denken zu kümmern.



  • @zeropage sagte in Was macht man mit solch einer Fehlermeldung?:

    Hm, was wäre denn besser? Ist ja nocht temporär.

    Ein array zum Beispiel. Ich weiß nicht, was das mit "temporär" zu tun hat.

    Wenn ich das Rect tranformieren will, benötige ich doch die Points?

    Ich verstehe nicht, was das mit der Frage, ob ein dynamisches Array (aka vector) das richtige ist, zu tun haben könnte.



  • @titan99_

    width ist gleich size() und das letzte Element ist size() - 1. Deshalb nehme ich nur die Punkte.

    Mein KO-System wird schon bei der Erstellung so gespiegelt, das y0 unten ist.



  • Der Vorteil bei 2 Punkten ist, dass garantiert ein Rechteck beschrieben wird. Wenn du einzelne Punkte bei deinem „Rechteck“ von außen veränderst (was ja bei einem Entwurf möglich war/ist), gilt dies nicht mehr.
    Ich würde, wenn du schon einen vector für die Punkte nimmst, mit einem allgemeinen Polygon anfangen. So kann auch aus einer Gerade ein Dreieck, aus einem Dreieck ein Viereck und daraus ein beliebiges Vieleck werden.
    Rotation, Skalierung, Hittest und Darstellung können für alle gleich behandelt werden und bei „kaputten“ Polygonen muss man ohnehin schauen, was man damit anstellen möchte (crossing/winding number).
    Spezialfälle können dann, falls nötig, später gesondert betrachtet werden.
    Vermutlich wäre es auch besser, die Originalpunkte separat zu speichern und die Darstellung und sonstigen Berechnungen dann mit anderen (eben den transformierten) Daten durchzuführen.



  • @zeropage sagte in Was macht man mit solch einer Fehlermeldung?:

    	val_t right() const { return points_[2].x(); }
    	val_t top() const { return points_[2].y(); }
    

    Sowas ist halt extrem ungut, wenn du nicht sicherstellst, dass "points_" wirklich mindestens 3 Elemente hat. Wie z.B. im Falle deines Default-Konstruktors. In dem Fall wäre dein Vector nämlich leer.
    Deswegen macht man solche "getter" eigentlich nicht.

    Im Fehlerfall bekommst du hier einen Segmentation-Fault und hast keine Ahnung wo dir das Ding gerade um die Ohren geflogen ist. Oder du bekommst irgendwelche Werte zurück, und hast plötzlich ein merkwürdig geformtes Rechteck.

    Ich schließe mich hier den Sportfreunden an, die sagen: Lieber das Rechteck durch zwei Punkte definieren ( oben-links, unten-rechts ). Vectoren oder Arrays sind hier nicht nötig.

    beim Vector bist du zudem noch vom Allokator abhängig, der möglicherweise, jetzt schon oder auch in Zukunft, mehr Speicher anfordert, als für 4 Elemente nötig ist. Garantieren kann dir das niemand.



  • @zeropage sagte in Was macht man mit solch einer Fehlermeldung?:

    @titan99_
    width ist gleich size() und das letzte Element ist size() - 1. Deshalb nehme ich nur die Punkte.

    Das hast du wohl mißverstanden: mit width und height sind die Ausmaße des Rechtecks gemeint, d.h.

    width = abs(right - left) + 1
    height = abs(bottom - top) + 1
    


  • @Th69 sagte in Was macht man mit solch einer Fehlermeldung?:

    Das hast du wohl mißverstanden: mit width und height sind die Ausmaße des Rechtecks gemeint, d.h.

    width = abs(right - left) + 1
    height = abs(bottom - top) + 1
    

    Huch, plus 1? Dann machst du aber die Annahme, dass es sich um Pixel oder andere diskrete Werte handelt und beide Grenzen inklusive sind.

    Wenn ich mit einem Rect auch ein "normales" Rechteck modellieren will, dann gehört die +1 da auf keinen Fall hin! Es fängt also schon bei so simplen Dingen an, dass man die Nutzung des Rect damit einschränkt. Ich sage das auch, weil das Ursprungs-Rect auch getemplatet war und man da bislang auch float oder double einsetzen konnte. Das +1 ergibt aber auch sowieso nur bei Ganzzahltypen Sinn.



  • Genau.
    Sogar wenn es sich um Pixel-Koordinaten handelt ist es nicht ganz unüblich den "right" und "bottom" Wert als exklusiv zu interpretieren. Ist zwar am Anfang komisch wenn man es noch nicht kennt, aber hat auch viele Vorteile.


  • Gesperrt

    @hustbaer Ist das bei glViewport so? Ich frage einfach, weil es normalerweise nicht auffallen würde. Also von 0 bis 3 würde 3-0+1=4 geben. Tönt nicht im vornherein ganz unsinnig, da, nein. Eher wird davon ausgegangen, dass mit den zweiten Argumenten die Grösse wie angegeben übernommen wird. Hoffentlich handhabt es dann aber z.B. GetClientRect gleich.



  • @titan99_ sagte in Was macht man mit solch einer Fehlermeldung?:

    Ist das bei glViewport so?

    Die Frage stellt sich ja nicht, da dort Breite und Höhe angegeben werden. Wenn du da Breite X angibst dann bekommst du auch Breite X.

    Also angenommen dein Fenster ist 100x100 Pixel gross, dann machst du glViewport(0, 0, 100, 100) und alles ist gut.
    Wenn du dagegen eine API hast wo du left/top/right/bottom angeben musst, dann ist die Frage ob du da 0/0/100/100 oder 0/0/99/99 angeben musst um das selbe zu erreichen. Und da ist es eben oft so dass du 0/0/100/100 angeben musst. Weil right und bottom eben oft exklusiv interpretiert werden.



  • Eine Menge Antworten inzwischen, hatte etwas Scheu, hier wieder reinzuschauen. Es gab ja viele Anregungen, und so wie ich manches verstehe, gibt es viele Spekulationen.
    Mein Rectzb ist dargestellt ein Polygon. Deshalb brauche ich auch vier Punkte, weil die Ecken nicht immer rechte und selbe Winkel sind. Das muss ich aber noch schauen, denn anfangs hatte ich ja auch nur zwei Point2D.

    Vielleicht wäre es hilfreich, wenn man noch meine Klasse Plot2D, wo das alles dargestellt wird, zeige, habe aber Angst, das dies einen Rattenschwanz an Vorschlägen bringt, wo man den Überblick verliert. Wenn schon das kleine Rectso ergiebig ist. Vielleicht in einem neuen Thread.

    Wenn es noch Anmerkungen gibt, die ich jetzt nicht berücksichtigt habe, gerne wiederholen. Wollte mich nur erstmal relativ zügig wieder melden.



  • Meine generelle Anmerkung ist, dass weniger manchmal mehr ist, insbesondere wenn der Anwendungsbereich schon von vorn beschränkt ist. Ist es zum Beispiel nötig, dass alles getemplatet ist? Templates verlängern die Compilezeit und machen den Code komplizierter. Würdest du irgendwas verlieren, wenn du die Klasse mit int-Koordinaten machst? Offenbar ist die ja zum Beispiel gar nicht für float-Zahlen oder gar komplexe Koordinaten geeignet.

    Andererseits ist es natürlich schön, eine generelle und wiederverwertbare Klasse zu haben.

    Ich finde aber, dass man die Diskussion insbesondere bei so etwas einachem wie 2 Punkten übertreiben kann.

    Am probelmatischten finde ich, dass nicht sofort an den Namen ersichtlich ist, das das alles soll. Bei deinem Dim gebe ich 2 Punkte in den Konstruktor (warum muss ich da 4 Einzelwerte statt 2 Punkte reintun, wo du doch Punkt2D hast?) und kann dann x() abfragen - hä? Verstehe schon die Berechnung nicht. Funktionsnamen wie toPoint und toLength schreien vom Namen her danach, Point und Length zu returnen, sind aber bei dir void. Brauchst du wirklich die 6 Member-Variablen? Das erscheint mir zu kompliziert.



  • Das Dim-Beispiel sollte nur zeigen, wie ich mich mit width- unhd height-Angaben schwer getan habe. Ist nicht mehr aktuell. Und lösche ich auch, weil es keinen Grund mehr gibt, darüber zu sprechen. Hatte aber bis dahin seine Arbeit getan.

    Bezüglich den templates habe ich auch in diese Richtung überlegt, ob zum Schluß, wenn eh nur noch mit bestimmten Typen gerechnet wird, nur diese zu verwenden. Aber ist ja keine große Änderung. Dann schreibe ich bei der betreffenden Klasse eben um, using val_t = float oder ähnlich.



  • Sorry, ich wollte nicht wieder undankbar wirken. Bzüglich der Dim-Klasse hätte ich nur "ja" antworten können, weil eben Geschichte.



  • @It0101 sagte in Was macht man mit solch einer Fehlermeldung?:

    @zeropage sagte in Was macht man mit solch einer Fehlermeldung?:

    	val_t right() const { return points_[2].x(); }
    	val_t top() const { return points_[2].y(); }
    

    Sowas ist halt extrem ungut, wenn du nicht sicherstellst, dass "points_" wirklich mindestens 3 Elemente hat. Wie z.B. im Falle deines Default-Konstruktors. In dem Fall wäre dein Vector nämlich leer.
    Deswegen macht man solche "getter" eigentlich nicht.

    Im Fehlerfall bekommst du hier einen Segmentation-Fault und hast keine Ahnung wo dir das Ding gerade um die Ohren geflogen ist. Oder du bekommst irgendwelche Werte zurück, und hast plötzlich ein merkwürdig geformtes Rechteck.

    Ich schließe mich hier den Sportfreunden an, die sagen: Lieber das Rechteck durch zwei Punkte definieren ( oben-links, unten-rechts ). Vectoren oder Arrays sind hier nicht nötig.

    Gut, dann bleibt es dabei:

    • gelöscht


  • so, hoffentlich finito.

    template<typename T>
    class Rect
    {
    	using val_t = T;
    public:
    	Rect(const val_t x0, const val_t y0, const val_t x, const val_t y) 
    		: p0{ x0, y0 }, p{ x, y } {}
    
    	val_t left() const { return p0.x; }
    	val_t bottom() const { return p0.y; }
    	val_t right() const { return p.x; }
    	val_t top() const { return p.y; }
    
    private:
    	struct point
    	{
    		val_t x = 0;
    		val_t y = 0;
    	} p0, p;
    };
    

Anmelden zum Antworten