Point - Vector from origin

Posted
Comments 0

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]

Author

Comments

There are currently no comments on this article.

Comment

Enter your comment below. Fields marked * are required. You must preview your comment before submitting it.