Part 7 of C++ tutorial – a 3D vector & transform library
A point is a position in 3D space, and can be represented by a vector from the origin.
A point has subtly different semantics from a vector. A vector can represent the translation from any point to any other, but a point represents a specific position.
Thus one can subtract one point from another to obtain the vector between them, but it makes no sense to add one position to another. Of course, you can add a vector to a point to obtain a new point, or you can add two vectors to obtain a single equivalent vector.
Therefore the addition and subtraction operations for a point are restricted accordingly. The following lists these:
p'=p+v (or p+=v )
p'=p-v (or p-=v )
v'=p'-p
Note that p'=v+p
is not catered for, being less readable. However, negation, as a scaling by -1, has been provided, despite readability – thus one can have p'=-p+v
or v'=p - -p
Although Point is represented by a Vector, it is not a vector per se, however, one may often wish to convert it directly to its representational Vector (rather than obtaining this by subtracting the origin from it), therefore an explicit conversion operator is provided:
explicit operator const Vector& () const { return *reinterpret_cast<const Vector*>(this); }
In other respects the Point class implementation is very similar to that of the Vector class.
There follows the code for the Point class, an example program, and its output:
class Point: protected VectorBase<XYZ>
{
protected:
explicit Point(const VectorBase<XYZ>& xyz):VectorBase<XYZ>(xyz) { }
public:
// Elements & accessors
using VectorBase<XYZ>::x;
using VectorBase<XYZ>::y;
using VectorBase<XYZ>::z;
explicit operator const double* () const { return array(); } // Cast to const array
explicit operator double* () { return array(); } // Cast to non-const array
const double& operator[](int i) const { return element(i); } // Const array element accessor
double& operator[](int i) { return element(i); } // Non-const array element accessor - for assignment
double* Read(double d[3]) const { return read(d); }
// Constructors
Point(double a,double b,double c):VectorBase<XYZ>(a,b,c) { }
explicit Point(const double d[3]):VectorBase<XYZ>(d[0],d[1],d[2]) { }
explicit Point(const Vector& v):VectorBase<XYZ>(v.x,v.y,v.z) { } // The point obtained by adding v to the origin
static const Point origin; // [0,0,0] - pre-constructed null
// Assignment
Point& operator=(const Point& p) { assign(p); return *this; }
// Conversions
explicit operator const Vector& () const { return *reinterpret_cast<const Vector*>(this); } // Can be cast to a const vector
// Informational
explicit operator bool() const { return !is_null(); } // True if not origin
bool operator!() const { return is_null(); }
bool operator==(const Point& p) const { return is_equal_to(p); }
bool operator!=(const Point& p) const { return !is_equal_to(p); }
// Operations
// Points may be transformed by a scalar
Point operator-() const { return Point(negation()); } // Equivalent to scaling by -1
Point& operator*=(double s) { multiply_by(s); return *this; }
Point& operator/=(double s) { divide_by(s); return *this; } // Throws div0
friend Point operator*(const Point& p,double s) { return Point(p.multiplication(s)); }
friend Point operator*(double s,const Point& p) { return Point(p.multiplication(s)); }
friend Point operator/(const Point& p,double s) { return Point(p.division(s)); } // Throws div0
// Transform point by vector addition
Point& operator+=(const Vector& v) { add(Point(v)); return *this; }
Point& operator-=(const Vector& v) { subtract(Point(v)); return *this; }
friend Point operator+(const Point& p,const Vector& v) { return Point(static_cast<const Vector&>(p)+v); }
friend Point operator-(const Point& p,const Vector& v) { return Point(static_cast<const Vector&>(p)-v); }
// Calculate vector between points
friend Vector operator-(const Point& p,const Point& q) { return static_cast<const Vector&>(p)-static_cast<const Vector&>(q); }
friend std::ostream& operator<<(std::ostream& os,const Point& p) { return os<<'['<<p.x<<','<<p.y<<','<<p.z<<']'; } // E.g. [1,2,3]
};
const Point Point::origin=Point(0,0,0);
int main() // The program
{ Point p=Point::origin;
const Vector v(1,2,3);
cout<<"p="<<p<<"\n";
cout<<"v="<<v<<"\n";
p+=v;
cout<<"p+=v: "<<p<<"\n";
p*=1.5;
cout<<"p*=1.5: "<<p<<"\n";
p-=v;
cout<<"p-=v: "<<p<<"\n";
return 0;
}
Program output:
p=[0,0,0]
v=(1,2,3)
p+=v: [1,2,3]
p*=1.5: [1.5,3,4.5]
p-=v: [0.5,1,1.5]
Comments
There are currently no comments on this article.
Comment