Suche ne Vector implementierung (nicht std::vector)



  • unskilled schrieb:

    Ich hör erst mal auf - hast es ja sicherlich gut gemeint... ^^

    Seine Fehler zu verbreiten kann nie gut gemeint sein. (wir haben ihn so weit ich mich erinnern kann mehrmals darauf hingewiesen die Initialisierungsliste usw. zu benutzen..)

    btw:
    Die Variablen bei einem Vector public zu machen finde ich duraus legitim. Eines der wenigen Ausnahmen der Regel.



  • drakon schrieb:

    Seine Fehler zu verbreiten kann nie gut gemeint sein.

    Klar wird das gut gemeint sein. Oder meinst du, er hat aus Bösartigkeit gepostet? 😉

    drakon schrieb:

    Die Variablen bei einem Vector public zu machen finde ich duraus legitim. Eines der wenigen Ausnahmen der Regel.

    👍 Gerade bei einer solchen fixen Schnittstelle, da nervt ein getX & setX nur.



  • Fehlt noch rescale und ein paar Rotationsoperationen 😃
    Dann wärs super



  • dennoch ist das ganze ein schlechtes Beispiel.



  • Badestrand schrieb:

    drakon schrieb:

    Seine Fehler zu verbreiten kann nie gut gemeint sein.

    Klar wird das gut gemeint sein. Oder meinst du, er hat aus Bösartigkeit gepostet? 😉

    Ne, das nicht, aber ich mag mich erinnern, dass wir ihn mehrmals darauf hingewiesen haben, dass er Initialisierungslisten usw. benutzen sollte und ihn auch auf andere Fehler seinerseits hingewiesen. Und das ignoriert er offensichtlich..
    Und somit ist dem OP überhaupt nicht geholfen, wenn er sich schlechte Methoden aneignet.



  • drakon schrieb:

    Ne, das nicht, aber ich mag mich erinnern, dass wir ihn mehrmals darauf hingewiesen haben, dass er Initialisierungslisten usw. benutzen sollte und ihn auch auf andere Fehler seinerseits hingewiesen.

    Sicher, das kann man trotzdem anders rüberbringen.

    Zum Thema: Bei solchen häufig verwendeten Konstrukten lohnt sich auch öfters ein Blick in die Google Codesuche, die Suche nach vec3d zeigt da schon einiges sinnvolles. Man muss halt die Lizenz beachten, aber sonst eine prima Möglichkeit für Inspirationen 🙂



  • Hab mal was gebastelt, in Anlehnung an ways Code.

    Verbesserungen immer gewünscht

    #pragma once
    
    #include <complex>
    #include <algorithm>
    
    class Vector
    {
    public: 
    
    	static double angleInBetweenDegree(const Vector & v1, const Vector &v2)
    	{
    		double angle = std::acos(v1.dotProduct(v2));
    		return std::min(angle, 360-angle);
    	}
    
    	Vector() {};
    
    	Vector(double new_x, double new_y, double new_z):x(new_x),y(new_y), z(new_z)
        {   
        }
    
        Vector operator+(const Vector &vector)
        {
            return Vector(vector.x+x, vector.y+y, vector.z+z);
        }
    
        Vector operator-(const Vector &vector)
        {
            return Vector(x-vector.x, y-vector.y, z-vector.z);
        }
    
        Vector operator*(const double number)
        {
            return Vector(x*number, y*number, z*number);
        }
    
        Vector operator/(const double number)
        {
            return Vector(x/number, y/number, z/number);
        }
    
    	bool operator==(const Vector & v) const
        {
    		return x == v.x && y == v.y && z == v.z;
        }
    
    	double dotProduct(const Vector &vector) const
    	{
    		return x*vector.x+y*vector.y+z*vector.z;
    	}
    
    	double length() const
    	{
    		return std::sqrt(std::pow(x,2.)+std::pow(y,2.)+std::pow(z,2.));
    	}
    
    	Vector crossProduct(const Vector &v) const
    	{
    		return Vector(y*v.z-z*v.y, z*v.x-x*v.z,x*v.y-y*v.x);
    	}
    
    	void rescale(double newScale)
    	{
    		normalize();
    		*this = *this * newScale;
    	}
    
    	void normalize()
    	{
    		*this =  *this* 1/length();
    	}
    
    	/**
    	 * Returs the angle of this vector in degrees from the X + plane from 0 to 360
    	 */
    	double angleInDegreeFromX() const
    	{
    		Vector v(1,0,0);
    
    		return Vector::angleInBetweenDegree(*this, v);
    	}
    
    // Public values for quick access until C++ provides C# like properties :D
    	double x;
    	double y;
    	double z;
    };
    

    Edit: sehe gerade das std::min in der static funzt nicht, hmmmmmmm why?



  • Seikilos schrieb:

    Edit: sehe gerade das std::min in der static funzt nicht, hmmmmmmm why?

    Du bist doch inzwischen lange genug dabei, um zu wissen dass wir keine Kristallkugeln haben, oder?



  • unskilled schrieb:

    - warsum sind x, y, z public?

    lol unskilled...

    drakon hat es eh schon gesagt, information hiding wäre hier unangebracht. Zum einen kann ein Vektor alle möglichen Werte die seine Datentypen aufnehmen können, annehmen, ohne dass er invalid wird, es gibt keine Invarianten einzuhalten. Die Respräsentation eines Vektors ist offensichtlich und eindeutig. Zum anderen ist Vektor - davon kann man glaube ich ausgehen - eine eher performance-kritische Klasse.

    Die Vektor-Klasse hat übrigens zu viele Member. Sollte man in freie Funktionen ändern. Kapselung spielt zwar keine Rolle, aber das wird sich später noch im Code bemerkbar machen, dass etwaige Rechnungen viel schöner formatieren.



  • // ...
    
    Vector a;
    Vector b;
    
    // ...
    
    Vector c;
    
    c = (a + b).length();
    // vs.
    c =vectorLength(a + b);
    

    Ein populäres Beispiel...



  • Die Vektor-Klasse hat übrigens zu viele Member. Sollte man in freie Funktionen ändern. Kapselung spielt zwar keine Rolle, aber das wird sich später noch im Code bemerkbar machen, dass etwaige Rechnungen viel schöner formatieren.

    Erstens das und dann kann ein Vektor auch andere Datentypen haben, also kann man da sehr schön eine template draus machen..

    Was aber definitiv da noch rein muss ist die Initialisierungsliste im Standardkonstruktor. Ansonsten kannst du dich auf sehr viel schöne, komische Sachen freuen, wenn du dein Code mal in Release kompilierst..

    Dann kann man da (fortgeschritten) noch ein wenig mit boost Operatoren auslagern.

    Habe ich hier mal für jemanden aus dem Forum gemacht. (Aber für einen Point, kommt aber auf das gleiche raus bei einem vektor..)
    http://www.spieleprogrammierer.de/phpBB2/viewtopic.php?t=10398&postdays=0&postorder=asc&start=0



  • drakon schrieb:

    Was aber definitiv da noch rein muss ist die Initialisierungsliste im Standardkonstruktor. Ansonsten kannst du dich auf sehr viel schöne, komische Sachen freuen, wenn du dein Code mal in Release kompilierst..

    Naja, darüber kann man auch wieder ein wenig streiten. Es gibt schon eine Reihe recht guten Argumenten, die dagegen sprechen:
    1.) Die builtins müssen auch von Hand initialisiert werden
    2.) Ein Vektor hat keinen eindeutigen Default-Wert (wobei ein Nullvektor natürlich naheliegend wäre)
    3.) Es kostet Zeit und nützt nicht viel.



  • drakon schrieb:

    ... und dann kann ein Vektor auch andere Datentypen haben, also kann man da sehr schön eine template draus machen..

    Was aber definitiv da noch rein muss ist die Initialisierungsliste im Standardkonstruktor. Ansonsten kannst du dich auf sehr viel schöne, komische Sachen freuen, wenn du dein Code mal in Release kompilierst..

    Dann kann man da (fortgeschritten) noch ein wenig mit boost Operatoren auslagern.

    dann nimm doch gleich den basic_vector<> hier aus dem Forum. Im selben Thread sind auch noch andere Varianten zu sehen.

    Gruß
    Werner



  • Richtig, aber

    Vektorklassenfachmann schrieb:

    Naja, darüber kann man auch wieder ein wenig streiten. Es gibt schon eine Reihe recht guten Argumenten, die dagegen sprechen:
    1.) Die builtins müssen auch von Hand initialisiert werden

    Ist ein vector ein Builtin? - Nein. Ich als User erwarte, dass es anständig 0-Initialisiert ist. (Muss nicht sein. Gut dokumentiert spricht eigl. nix dagegen das nicht zu machen.)

    Vektorklassenfachmann schrieb:

    2.) Ein Vektor hat keinen eindeutigen Default-Wert (wobei ein Nullvektor natürlich naheliegend wäre)

    Ich würde sagen, dass die Member von einem Vektor 0-initialisiert sind, dann ist auch der Vektor 0-initialisiert..

    Vektorklassenfachmann schrieb:

    3.) Es kostet Zeit und nützt nicht viel.

    Da stimme ich dir nicht zu. Es kostet definitiv mehr Zeit,aber das ist im Normalfall nicht das Problem. Es nützt schon, da es Fehler zuvorkommen kann, wo man sich auf 0-Initialisierung verlässt.
    Bei einer Matrix ist das z.B wieder eine andere Frage. Wenn z.B viele Matrizen ständig erzeugt und zerstört werde, kann es durchaus ein Flaschenhals werden. Bei einem Vektor ist das aber imo weniger der Fall. (Ich habe eine Sprite-Engine, die ständig neue Objekte erstellt, die Hauptsächlich Vektoren beinhaltet und die Erzeugung ist nich annährend im Optimierkritischen Bereich..;))



  • 1.) Die builtins müssen auch von Hand initialisiert werden

    EDIT:
    Doch, jetzt habe ich den Satz verstanden. Meine Antwort war quatsch.

    2.) Ein Vektor hat keinen eindeutigen Default-Wert (wobei ein Nullvektor natürlich naheliegend wäre)

    Zumindest sollte klar sein ob der Vector sinnige Werte enthält. Da ist alles besser als ein undefinierter Vektor (es seidenn, dieser hätte ein isValid Flag o.ä.)

    3.) Es kostet Zeit und nützt nicht viel.

    Was kostet Zeit? Das Coden oder die Konstruktion?



  • Meine Vorschläge:
    1. Ich würde den Typ der Klasse zum Template machen
    2. Ich würde die dimension als Template übergeben

    template<class T, int DIM>
    class Vector
    {
      T getVal(int dim);
      void setVal(int dim, T val);
    
    private:
      T m_vec[DIM];
    
    }
    

    3. ich würde getter und setter schreiben (für spezialisierte 2d und 3d Templates).
    da vekoren aber ein standardkonstrukt sind, würde ich die zugriffsfunktionen kurz halten:

    T x()const
    { return m_vec[0];}
    T y()const
    { return m_vec[1];}
    T z()const
    { return m_vec[2];}
    
    T& x()
    { return m_vec[0];}
    T& y()
    { return m_vec[1];}
    T& z()
    { return m_vec[2];}
    

    Das ist zwar nicht ganz so üblich, aber das Kombiniert die Vorteile von getter/Setter mit einfacher Benutzbarkeit.
    man kann dann sowas schreiben.

    Point<float,3> p;
     p.x() += 3;
    


  • Da ich mit openscenegraph vertraut bin, nehme ich die Vektorklassen davon.

    btw würde Typisierung sich nicht eher negativ auf die Performance auswirken?



  • Seikilos schrieb:

    static double angleInBetweenDegree(const Vector & v1, const Vector &v2)
    	{
    		double angle = std::acos(v1.dotProduct(v2));
    		return std::min(angle, 360-angle);
    	}
    

    eigentlich gilt doch:

    φ = ZWischenwinkel
    a = der eine Vektor
    b = der andere Vektor
    ° = Ersatz für das Skalarproduktzeichen
    cos φ = (a°b)/(|a|*|b|)
    sprich bei deinem "angleInBetweenDegree" fehlt die Division durch das Produkt der 2 Vektorlängen
    außerdem gibt std::acos doch rad-Angaben und keine Gradangaben (also Grad im Sinne von Degree) zurück oder?

    :xmas1:



  • drakon, wie oft benötigst du einen Nullvektor? Und wie oft kommst du in eine Situation, in der du z.B. viele Vektoren in einem std::vector "vorbereitest", um sie später mit anständigen Werten zu befüllen. Die Null-Initialisierung hat dir dann nichts gebracht.

    Für mich erscheint ein Fall, in dem man wirklich Nullvektoren benötigt, ein wenig konstruiert. Auf jeden Fall sollten die seltener sein, als jene, in denen man Vektoren erzeugt aber erst später mit anständigen Werten belegt. Das kann man zwar bestimmt oftmals auch optimieren, aber das bleibt trotzdem meine Meinung.

    Und der Vergleich zu Matrizen... Angenommen, ich habe dreimal so viele Vektoren, als Matrizen. Dann habe ich einen äquivalenten Flaschenhals, natürlich von 3x3 Matrizen ausgehend.

    LordJaxom, wie sinnig ist ein Nullvektor? Man definiert damit Undefiniertheit, was für einen Vektor nicht wirklich viel Sinn macht. Bei Zeigern schreibe ich oft Code, der von der Gültigkeit des Zeigers abhängt. Wie oft mache ich das für Vektoren? Wenn ich einen Vektor verwende bevor ich ihn mit korrekten Werten belegt habe, führt es in beiden Fällen zu einem Fehler. Ein Nullvektor erleichtert das Debugging unwesentlich, in der Release-Version bietet er gar keine Vorteile mehr.

    Ein isValid-Flag sollte eine Vektorklasse selbst nicht haben, höchstens eine Klasse die Vektoren hält und für ein solches Flag auch einen guten Grund hat (ein Vektorenmanager meinetwegen 🙄 ... ich weiß im Moment keinen guten Anwendungsfall!)

    Zeit kostet es natürlich bei der Konstruktion.



  • wth, ich sagte doch bereits das er den Vektor als eigene Klasse initialisieren sollte, dann gibts kein typedef struct und keine public Variablen.


Anmelden zum Antworten