CPoint für 3 Dimensionen?
-
jo sry. ... man müsste auch noch getter und setter einbauen
-
Da fehlt noch so einiges.
Als Vorbild für eigene Entwürfe würde ich mal so was nehmen:
http://www.codeproject.com/cpp/geometry.aspclass C3Point { // Attributes public: REAL x,y,z; //Operations public: C3Point() {} C3Point(double a, double b, double c) { x = D2Real(a); y = D2Real(b); z = D2Real(c); } REAL Length2() { return (x*x + y*y + z*z); } REAL Length() { return D2Real(sqrt(x*x + y*y + z*z)); } void Scale(REAL factor) { x *= factor; y *= factor; z *= factor; } void Normalise(); void operator=(C3Point& P) { x = P.x; y = P.y; z = P.z; } // assign C3Point operator-(C3Point P) { return C3Point(x-P.x, y-P.y, z-P.z); } // subtract C3Point operator-() { return C3Point(-x, -y, -z); } // unary - C3Point operator+(C3Point P) { return C3Point(x+P.x, y+P.y, z+P.z); } // add C3Point operator+=(C3Point P) { x += P.x; y += P.y; z += P.z; return *this; } // add += C3Point operator-=(C3Point P) { x -= P.x; y -= P.y; z -= P.z; return *this; } // subtract -= REAL operator*(C3Point P) { return x*P.x + y*P.y + z*P.z; } // dot product C3Point operator*(REAL f) { return C3Point(x*f, y*f, z*f); } // scalar product C3Point operator/(REAL f) { return C3Point(x/f, y/f, z/f); } // scalar div C3Point operator*=(REAL f) { x *= f; y *= f; z *= f; return *this; } // scalar mult *= C3Point operator/=(REAL f) { x /= f; y /= f; z /= f; return *this; } // scalar div /= C3Point operator^(C3Point P) { return C3Point(y*P.z-P.y*z, P.x*z-x*P.z, x*P.y-P.x*y); } // cross product BOOL operator==(C3Point& P); // is equal to? BOOL operator!=(C3Point& P) { return !(*this == P); } // is not equal to? };
-
Hi!
Paar Verbesserungsvorschläge:
class C3Point { // Attributes public: REAL x,y,z; //Operations public: C3Point() {} // x, y, z initialisieren C3Point(double a, double b, double c) { x = D2Real(a); y = D2Real(b); z = D2Real(c); } // initialisierungsliste REAL Length2() { return (x*x + y*y + z*z); } // const REAL Length() { return D2Real(sqrt(x*x + y*y + z*z)); } // const void Scale(REAL factor) { x *= factor; y *= factor; z *= factor; } void Normalise(); void operator=(C3Point& P) { x = P.x; y = P.y; z = P.z; } // return C3Point referenz C3Point operator-(C3Point P) { return C3Point(x-P.x, y-P.y, z-P.z); } // const C3Point operator-() { return C3Point(-x, -y, -z); } // const C3Point operator+(C3Point P) { return C3Point(x+P.x, y+P.y, z+P.z); } // const C3Point operator+=(C3Point P) { x += P.x; y += P.y; z += P.z; return *this; } // Referenz zurückgeben... C3Point operator-=(C3Point P) { x -= P.x; y -= P.y; z -= P.z; return *this; } // Referenz zurückgeben... REAL operator*(C3Point P) { return x*P.x + y*P.y + z*P.z; } // const C3Point operator*(REAL f) { return C3Point(x*f, y*f, z*f); } // const C3Point operator/(REAL f) { return C3Point(x/f, y/f, z/f); } // float invf = 1.0f/ f; x*=f y*=f z*=f (is schneller), const C3Point operator*=(REAL f) { x *= f; y *= f; z *= f; return *this; } // Referenz zurückgeben C3Point operator/=(REAL f) { x /= f; y /= f; z /= f; return *this; } // multiplizieren mit ( 1.0f/ f ), und Referenz C3Point operator^(C3Point P) { return C3Point(y*P.z-P.y*z, P.x*z-x*P.z, x*P.y-P.x*y); } // const BOOL operator==(C3Point& P); // const BOOL operator!=(C3Point& P) { return !(*this == P); } // const };
-
Copyconstructor und evt. union.
-
Wir nennen das ab sofort einfach vector und siehe da wir finden tausende fertiger klassen im netz..
-
#pragma once class CVector3 { public: // Variablen union { struct { float x; // Koordinaten float y; float z; }; struct { float u; // Texturkoordinaten float v; float w; }; float c[3]; // Array der Koordinaten }; // Konstruktoren CVector3() {}; CVector3(const CVector3& v) : x(v.x), y(v.y), z(v.z) {}; CVector3(const float f) : x(f), y(f), z(f) {}; CVector3(const float _x, const float _y, const float _z) : x(_x), y(_y), z(_z) {}; CVector3(const float* pfComponent) : x(pfComponent[0]), y(pfComponent[1]), z(pfComponent[2]) {}; // Casting-Operatoren operator float* () { return (float*)(c); }; // Zuweisungsoperatoren CVector3& operator = (const CVector3& v) { x = v.x; y = v.y; z = v.z; return *this; }; CVector3& operator += (const CVector3& v) { x += v.x; y += v.y; z += v.z; return *this; }; CVector3& operator -= (const CVector3& v) { x -= v.x; y -= v.y; z -= v.z; return *this; }; CVector3& operator *= (const CVector3& v) { x *= v.x; y *= v.y; z *= v.z; return *this; }; CVector3& operator *= (const float f) { x *= f; y *= f; z *= f; return *this; }; CVector3& operator /= (const CVector3& v) { x /= v.x; y /= v.y; z /= v.z; return *this; }; CVector3& operator /= (const float f) { x /= f; y /= f; z /= f; return *this; }; }; // Arithmetische Operatoren inline CVector3 operator + (const CVector3& a, const CVector3& b) { return CVector3(a.x + b.x, a.y + b.y, a.z + b.z); }; inline CVector3 operator - (const CVector3& a, const CVector3& b) { return CVector3(a.x - b.x, a.y - b.y, a.z - b.z); }; inline CVector3 operator - (const CVector3& v) { return CVector3(-v.x, -v.y, -v.z); }; inline CVector3 operator * (const CVector3& a, const CVector3& b) { return CVector3(a.x * b.x, a.y * b.y, a.z * b.z);} inline CVector3 operator * (const CVector3& v, const float f) { return CVector3(v.x * f, v.y * f, v.z * f); }; inline CVector3 operator * (const float f, const CVector3& v) { return CVector3(v.x * f, v.y * f, v.z * f); }; inline CVector3 operator / (const CVector3& a, const CVector3& b) { return CVector3(a.x / b.x, a.y / b.y, a.z / b.z); }; inline CVector3 operator / (const CVector3& v, const float f) { return CVector3(v.x / f, v.y / f, v.z / f); }; // Vergleichsoperatoren inline bool operator == (const CVector3& a, const CVector3& b) { if(a.x != b.x) return false; if(a.y != b.y) return false; return a.z == b.z; }; inline bool operator != (const CVector3& a, const CVector3& b) { if(a.x != b.x) return true; if(a.y != b.y) return true; return a.z != b.z; } // Funktionen deklarieren inline float CVector3Length(const CVector3& v) { return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); }; inline float CVector3LengthSq(const CVector3& v) { return v.x * v.x + v.y * v.y + v.z * v.z; }; inline CVector3 CVector3Normalize(const CVector3& v) { return v / sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); }; inline CVector3 CVector3NormalizeEx(const CVector3& v) { return v / (sqrtf(v.x * v.x + v.y * v.y + v.z * v.z) + 0.0001f); }; inline CVector3 CVector3Cross(const CVector3& v1, const CVector3& v2) { return CVector3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); }; inline float CVector3Dot(const CVector3& v1, const CVector3& v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; }; inline float CVector3Angle(const CVector3& v1, const CVector3& v2) { return acosf((v1.x * v2.x + v1.y * v2.y + v1.z * v2.z) / sqrtf((v1.x * v1.x + v1.y * v1.y + v1.z * v1.z) * (v2.x * v2.x + v2.y * v2.y + v2.z * v2.z))); }; inline CVector3 CVector3InterpolateCoords(const CVector3& v1, const CVector3& v2, const float p) {return v1 + p * (v2 - v1); }; inline CVector3 CVector3InterpolateNormal(const CVector3& v1, const CVector3& v2, const float p) {return CVector3NormalizeEx(v1 + p * (v2 - v1)); }; inline CVector3 CVector3Min(const CVector3& v1, const CVector3& v2) { return CVector3(TB_MIN(v1.x, v2.x), TB_MIN(v1.y, v2.y), TB_MIN(v1.z, v2.z)); }; inline CVector3 CVector3Max(const CVector3& v1, const CVector3& v2) { return CVector3(TB_MAX(v1.x, v2.x), TB_MAX(v1.y, v2.y), TB_MAX(v1.z, v2.z)); };
Der Vektor kommt ursprünglich aus der TriBase Engine. Wurde von mir aber abgeändert, um ihn auch ausserhalb der TriBase Engine und ohne DirectX benutzen zu können. Die TriBase Engine ist Gratis und darf frei weiterverteilt werden. Auch ihr Inhalt darf man verändern und dann weiterverteilen. Also es hat da kein Copyright Problem oder sowas, wenn ihr dies da oben braucht ^^
Grüssli
-
Naja, is auch nich überall ganz rund, ne?
-
Gibt es irgendwo eine allgemeine Klasse für n-dimensionale Punkte bzw. Vektoren?
-
Erhard Henkes schrieb:
Gibt es irgendwo eine allgemeine Klasse für n-dimensionale Punkte bzw. Vektoren?
Ja klar, hier.
-
Da ja schon einige mehr oder weniger gelungene Implementierungen von einem Vektor mit drei Dimensionen die Runde gemacht haben, will ich Euch meine Variante nicht vorenthalten.
#include <boost/operators.hpp> #include <iostream> #include <cmath> template< typename T > class basic_vector : boost::additive< basic_vector< T >, boost::multiplicative< basic_vector< T >, T, boost::modable< basic_vector< T > > > > { public: typedef T value_type; basic_vector() : m_x(), m_y(), m_z() {} basic_vector( value_type x, value_type y, value_type z = value_type() ) : m_x( x ), m_y( y ), m_z( z ) {} // Addition, Subtraktion basic_vector& operator+=( const basic_vector& b ) { m_x += b.m_x; m_y += b.m_y; m_z += b.m_z; return *this; } basic_vector& operator-=( const basic_vector& b ) { m_x -= b.m_x; m_y -= b.m_y; m_z -= b.m_z; return *this; } // Multiplikation, Division mit einem Skalar basic_vector& operator*=( value_type f ) { m_x *= f; m_y *= f; m_z *= f; return *this; } basic_vector& operator/=( value_type f ) { m_x /= f; m_y /= f; m_z /= f; return *this; } // Betrag friend value_type abs( const basic_vector& v ) { using namespace std; return sqrt( v.m_x * v.m_x + v.m_y * v.m_y + v.m_z * v.m_z ); } // Skalerprodukt value_type operator*( const basic_vector& b ) const { return m_x * b.m_x + m_y * b.m_y + m_z * b.m_z } // Kreuzprodukt basic_vector operator%=( const basic_vector& b ) { const value_type x = m_y * b.m_z - m_z * b.m_y; const value_type y = m_z * b.m_x - m_x * b.m_z; m_z = m_x * b.m_y - m_y * b.m_x; m_x = x; m_y = y; return *this; } friend std::ostream& operator<<( std::ostream& out, const basic_vector& v ) { return out << v.m_x << " " << v.m_y << " " << v.m_z; } private: value_type m_x, m_y, m_z; }; typedef basic_vector< double > Vector;
Der Vektor bietet alle üblichen Vektor-Operationen an; benutzt boost.operators um redundanten Code zu vermeiden und der Typ der Einheit ist frei wählbar; default ist double.
Ganz absichtlich sind weder Getter/Setter-Methoden noch Vergleichsoperatoren enthalten.
Andere Methoden bzw. (friend-)Funktionen wie Orthogonale oder min/max sind nach eigenem Bedarf hinzuzufügen.
Gruß
Werner
-
Das is dochmal was...
Ich versteh nur nicht warum jeder lieber Dividiert wenn man genausogut Multiplizieren kann. Multiplikationen von Fließkommazahlen ist schneller, wirklich!!!grüße
-
Eine interessante Sammlung. Danke für den Hinweis auf boost.
-
David_pb schrieb:
Multiplikationen von Fließkommazahlen ist schneller, wirklich!!!
Versteh' ich Dich richtig, dass
basic_vector& operator/=( value_type f ) { return *this *= (value_type(1)/f); }
schneller sein soll, als
basic_vector& operator/=( value_type f ) { m_x /= f; m_y /= f; m_z /= f; return *this; }
wäre mir neu. Um wieviel? Hast Du's gemessen?
Fragt
Werner
-
Ja, sollte schneller sein. Evtl solltest du nicht den *= Operator verwenden sondern direkt Implementieren.
Ich habs auch mal gemessen, bei mir was bis zu drei mal schneller mit der Multiplikation.grüße
-
Warum verzichtet ihr auf SIMD? Ne gute Klasse prüft ob SIMD vorhanden ist und verwendet SIMD.
Alternativ: Die Mathe-Funktionen aus DirectX machen das schon und man verwendet einfach DirectX.
-
David_pb schrieb:
Ja, sollte schneller sein. Evtl solltest du nicht den *= Operator verwenden sondern direkt Implementieren.
Ich habs auch mal gemessen, bei mir was bis zu drei mal schneller mit der Multiplikation.grüße
Ja Wahnsinn, Du hast Recht. Das ist signifikant schneller - bei mir mehr als Faktor 10.
Die direkte Implementierung bringt übrigens gar nichts. Das kann man so lassen wie in meinem letzten Posting.Man lernt doch nie aus.
Danke & Gruß
Werner
-
Division ist immer langsamer wie eine Multiplikation, das wird dir jeder bestätigen der mal den schaltplan für beides erstellt hat. Und oben ist es ja eine Float-Division und die wurde ja gegen die Float-Multiplikation getauscht, das muss schneller sein.
-
Ich such gerade den Sinn deines Posts... Das die Division schneller ist war ja bereits geklärt...
-
Lolz schrieb:
Warum verzichtet ihr auf SIMD? Ne gute Klasse prüft ob SIMD vorhanden ist und verwendet SIMD.
Alternativ: Die Mathe-Funktionen aus DirectX machen das schon und man verwendet einfach DirectX.Meine Rede. f'`8k
Gruß, TGGC (\-/ returns)
-
Es soll den Fall geben das man unabhängig von DirectX bleiben will, z.B. wenn man OpenGL als API verwendet...
Aber die Verwendung von SIMD macht schon Sinn, soweit der Prozessor mitspielt!grüße