Sign in to follow this  

2D Vector and Point template classes

This topic is 3044 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys, i have implemented and slightly modified some code i found for 2D vector and point classes. But i am a bit stumped trying to make them template classes. Posting here is a last resort, i have looked on google already but searching for "vector" comes up with std::vectors and "point" thinks i mean pointer. Anyway, i am having trouble specifically with referring to the Vector class in the class definition of Point. I don't know how to correctly declare it (without causing cyclic dependency). Here is the code. (Note: the code may be freely used and modified and i have included the copyright notice with it) Point.h
/////////////////////////////////////////////////////////////////////
// File: Vector.h                                                  //
// Date: 11/8/09                                                   //
// Desc: 2D vector definition. Modified from http://softsurfer.com //
//                                                                 //
//  Copyright 2003, softSurfer (www.softsurfer.com)                //
//  This code may be freely used and modified for any purpose      //
//  providing that this copyright notice is included with it.      //
//  SoftSurfer makes no warranty for this code, and cannot be held //
//  liable for any real or imagined damage resulting from its use. //
//  Users of this code must verify correctness for their           //
//  application.                                                   //
//                                                                 //
/////////////////////////////////////////////////////////////////////

#ifndef _POINT_H_
#define _POINT_H_

#include <math.h>

namespace physics {

template <class T>
class Vector;

template <class T>
class Point {
    friend Vector<T>;
public:
    T x, y;

    Point() : x(0), y(0) {}
    Point(T x, T y) : x(x), y(y) {}
	~Point() {};

	//----------------------------------------------------------
	// Comparison
	bool operator==(Point);
	bool operator!=(Point);

	//----------------------------------------------------------
	// Point and Vector Operations (always valid) 
	Vector operator-(Point);       // Vector difference
	Point  operator+(Vector);      // +translate
	Point  operator-(Vector);      // -translate
	Point& operator+=(Vector);     // inc translate
	Point& operator-=(Vector);     // dec translate

	//----------------------------------------------------------
	// Point Scalar Operations (convenient but often illegal)
	// using any type of scalar (int, float, or double)
	//    are not valid for points in general,
	//    unless they are 'affine' as coeffs of 
	//    a sum in which all the coeffs add to 1,
	//    such as: the sum (a*P + b*Q) with (a+b == 1).
	//    The programmer must enforce this (if they want to).

	// Scalar Multiplication
	friend Point operator*(T, Point);
	friend Point operator*(Point, T);
	// Scalar Division
	friend Point operator/(Point, T);

	//----------------------------------------------------------
	// Point Addition (also convenient but often illegal)
	//    is not valid unless part of an affine sum.
	//    The programmer must enforce this (if they want to).
	friend Point operator+(Point, Point);     // add points

	//----------------------------------------------------------
	// Point Relations
	friend T dist(Point, Point);         // Distance
	friend T distSquared(Point, Point);  // Distance^2
};

}  // namespace physics

#endif  // _POINT_H_




Point.cpp
#include "ballistic/include.h"
#include "Point.h"
#include "Vector.h"
using namespace physics;


//------------------------------------------------------------------
// Comparison
//------------------------------------------------------------------

template <class T>
bool Point<T>::operator==(Point<T> q) {
	return (x == q.x && y == q.y);
}

template <class T>
bool Point<T>::operator!=(Point<T> q) {
	return (x != q.x || y != q.y);
}

//------------------------------------------------------------------
// Point Vector Operations
//------------------------------------------------------------------

template <class T>
Vector<T> Point<T>::operator-(Point<T> q) {   // Vector diff of Points
	Vector<T> v;
	v.x = x - q.x;
	v.y = y - q.y;
	return v;
}

template <class T>
Point<T> Point<T>::operator+(Vector<T> v) {   // +ve translation
	Point<T> p;
	p.x = x + v.x;
	p.y = y + v.y;
	return p;
}

template <class T>
Point<T> Point<T>::operator-(Vector<T> v) {   // -ve translation
	Point<T> p;
	p.x = x - v.x;
	p.y = y - v.y;
	return p;
}

template <class T>
Point<T>& Point<T>::operator+=(Vector<T> v) { // +ve translation
	x += v.x;
	y += v.y;
	return *this;
}

template <class T>
Point<T>& Point<T>::operator-=(Vector<T> v) { // -ve translation
	x -= v.x;
	y -= v.y;
	return *this;
}

//------------------------------------------------------------------
// Point Scalar Operations (convenient but often illegal)
//        are not valid for points in general,
//        unless they are 'affine' as coeffs of 
//        a sum in which all the coeffs add to 1,
//        such as: the sum (a*P + b*q) with (a+b == 1).
//        The programmer must enforce this (if they want to).
//------------------------------------------------------------------

template <class T>
Point<T> operator*(T c, Point<T> q) {
	Point<T> p;
	p.x = c * q.x;
	p.y = c * q.y;
	return p;
}

template <class T>
Point<T> operator*(Point<T> q, T c) {
	Point<T> p;
	p.x = c * q.x;
	p.y = c * q.y;
	return p;
}

template <class T>
Point<T> operator/(Point<T> q, T c) {
	Point<T> p;
	p.x = q.x / c;
	p.y = q.y / c;
	return p;
}

//------------------------------------------------------------------
// Point Addition (also convenient but often illegal)
//    is not valid unless part of an affine sum.
//    The programmer must enforce this (if they want to).
//------------------------------------------------------------------
template <class T>
Point<T> operator+(Point<T> q, Point<T> r) {
	Point<T> p;
	p.x = q.x + r.x;
	p.y = q.y + r.y;
	return p;
}

//------------------------------------------------------------------
// Distance between Points
//------------------------------------------------------------------

template <class T>
T dist(Point<T> p, Point<T> q) {      // Euclidean distance
	T dx = p.x - q.x;
	T dy = p.y - q.y;
	return sqrt(dx*dx + dy*dy);
}

template <class T>
T distSquared(Point<T> p, Point<T> q) {// squared distance (more efficient)
	T dx = p.x - q.x;
	T dy = p.y - q.y;
	return (dx*dx + dy*dy);
}




Vector.h
#ifndef _VECTOR_H_
#define _VECTOR_H_

#include "Point.h"

namespace physics {

template <class T>
class Vector : public Point<T> {
public:
    Vector() : x(0), y(0) {}
    Vector(T x, T y) : x(x), y(y) {}
    static Vector fromPolar(T dist, double angle);

    T length() { return (T)sqrt(x*x + y*y); }

    //----------------------------------------------------------
	// Vector Unary Operations
	Vector operator-();                // unary minus
	Vector operator~();                // unary 2D perp operator

	//----------------------------------------------------------
	// Scalar Multiplication
	friend Vector operator*(T, Vector);
	friend Vector operator*(Vector, T);
	// Scalar Division
	friend Vector operator/(Vector, T);

	//----------------------------------------------------------
	// Vector Arithmetic Operations
	Vector operator+(Vector);      // vector add
	Vector operator-(Vector);      // vector subtract
	T operator*(Vector);           // inner dot product
	T operator|(Vector);           // 2D exterior perp product

	Vector& operator*=(T);         // vector scalar mult
	Vector& operator/=(T);         // vector scalar div
	Vector& operator+=(Vector);    // vector increment
	Vector& operator-=(Vector);    // vector decrement

    // Returns a normalized vector from this one
    Vector normalized();

    // Normalizes the given vector
    static void normalize(Vector& v);
};

}  // namespace physics

#endif  // _VECTOR_H_




Vector.cpp
#include "ballistic/include.h"
#include "Vector.h"
using namespace physics;


template <class T>
Vector<T> Vector<T>::fromPolar(T dist, double angle) {
    return Vector((T)(dist * cos(degToRad(angle))),
                  (T)(dist * sin(degToRad(angle))));
}

//------------------------------------------------------------------
//  Unary Ops
//------------------------------------------------------------------

// unary minus
template <class T>
Vector<T> Vector<T>::operator-() {
	Vector<T> v;
	v.x = -x; v.y = -y;
	return v;
}

// unary 2D perp operator
template <class T>
Vector<T> Vector<T>::operator~() {
	Vector<T> v;
	v.x = -y; v.y = x;
	return v;
}

//------------------------------------------------------------------
//  Scalar Ops
//------------------------------------------------------------------

// Scalar Multiplies
template <class T>
Vector<T> operator*(T c, Vector<T> w) {
	Vector<T> v;
	v.x = c * w.x;
	v.y = c * w.y;
	return v;
}

template <class T>
Vector<T> operator*(Vector<T> w, T c) {
	Vector<T> v;
	v.x = c * w.x;
	v.y = c * w.y;
	return v;
}

// Scalar Divides
template <class T>
Vector<T> operator/(Vector<T> w, T c) {
	Vector<T> v;
	v.x = w.x / c;
	v.y = w.y / c;
	return v;
}

//------------------------------------------------------------------
//  Arithmetic Ops
//------------------------------------------------------------------

template <class T>
Vector<T> Vector<T>::operator+(Vector<T> w) {
	Vector<T> v;
	v.x = x + w.x;
	v.y = y + w.y;
	return v;
}

template <class T>
Vector<T> Vector<T>::operator-(Vector<T> w) {
	Vector<T> v;
	v.x = x - w.x;
	v.y = y - w.y;
	return v;
}

//------------------------------------------------------------------
//  Products
//------------------------------------------------------------------

// Inner Dot Product
template <class T>
T Vector<T>::operator*(Vector<T> w) {
	return (x * w.x + y * w.y);
}

// 2D Exterior Perp Product
template <class T>
T Vector<T>::operator|(Vector<T> w) {
	return (x * w.y - y * w.x);
}

//------------------------------------------------------------------
//  Shorthand Ops
//------------------------------------------------------------------

template <class T>
Vector<T>& Vector<T>::operator*=(T c) {         // vector scalar mult
	x *= c;  y *= c;
	return *this;
}

template <class T>
Vector<T>& Vector<T>::operator/=(T c) {         // vector scalar div
	x /= c;  y /= c;
	return *this;
}

template <class T>
Vector<T>& Vector<T>::operator+=(Vector<T> w) { // vector increment
	x += w.x;  y += w.y;
	return *this;
}

template <class T>
Vector<T>& Vector<T>::operator-=(Vector<T> w) { // vector decrement
	x -= w.x;  y -= w.y;
	return *this;
}

template <class T>
Vector<T> Vector<T>::normalized() {
    if (x == 0 && y == 0) return Vector();
    T len = length();
    Vector<T> v;
    v.x = x / len;
    v.y = y / len;
    return v;
}

template <class T>
void Vector<T>::normalize(Vector& v) {
    if (v.x == 0 && v.y == 0) return;
	T len = v.length();
    v.x /= len;
    v.y /= len;
}




I have had trouble compiling it, the current error i get is:
Point.cpp
.\physics\Point.cpp(54) : error C2371: 'physics::Point<T>::operator +' : redefinition; different basic types
        c:\...\physics\Point.h(44) : see declaration of 'physics::Point<T>::operator +'
I would really appreciate it if someone could explain what i am doing wrong. thanks [Edited by - XTAL256 on August 16, 2009 4:17:09 AM]

Share this post


Link to post
Share on other sites
You shouldn't separate the definition of your template class from its declaration.
The definition of your template class and its declaration should reside in the same file. There should only be one file, for example, "Point.h", where everything is defined and implemented.
In short, put all that are inside your ".cpp" files inside their corresponding ".hpp" files.

Share this post


Link to post
Share on other sites
Besides what johnstanp said (which is sadly true), I have a few random comments.

The way Mathematicians usually look at these things, vectors are more basic entities than points and can be defined without making any reference to points.

In Affine Geometry, once you pick a point as the origin you can describe any point as "the origin plus some vector". Then it makes sense to represent a point by that vector.

Scalar multiplication and division are not well-defined operations on points, since the result depends on your selection of origin. I wouldn't provide them. Same thing goes for addition of points. There is an argument for providing these operations in that it makes it possible to write expressions like `M = (P + Q) / 2;', which is a valid operation, because what you are doing is computing a barycenter. I think I prefer to provide an explicit function to compute the barycenter if I need one.

I wouldn't overload operators ~, * and | for vectors to represent "take a perpendicular", "dot product" and "2D exterior perp product" (I didn't even have a name for this operation), because they are not standard enough, so people will have a hard time understanding code that uses them. I would much rather see functions used for this purpose: `perp(v)', `dot(v,w)' and `exterior_perp_product(v,w)'. If anything, what you are calling `v|w' should be called `v^w', because that operation is almost identical to the wedge product.

What's the point of having all those `friend' declarations if everything in your classes is public?

Share this post


Link to post
Share on other sites
Here are a few quick observations about your code (in addition to what johnstanp posted):

1. Symbols that start with an underscore followed by a capital letter are reserved by the implementation, so I would recommend just using (e.g.) POINT_H_ or POINT_H rather than _POINT_H_.

2. Since you're using C++, the correct header to include would be cmath rather than math.h.

3. This is somewhat subjective, but I wouldn't put general math classes in a 'physics' namespace (such classes can be used in many contexts, not just physics).

4. Don't implement empty non-virtual destructors (the compiler-generated destructor will suffice in this case).

5. Binary operators are usually best implemented as non-member functions (read any of the many previous threads on vector and matrix classes for more info on this). It looks like you've implemented some of the binary operators this way, but not all of them.

6. Unless I'm missing something, the non-member functions don't need to be friends of the classes (since the data is all public).

7. Implement operator!= as return !(a==b) (following the principle of code reuse).

8. Code such as:
Vector<T> v;
v.x = x - q.x;
v.y = y - q.y;
return v;
Can be more concisely written as:
return Vector<T>(x - q.x, y - q.y);
I'll also just offer my personal opinion on something. Occasionally you'll come across long, spirited discussions online as to whether a math library should have separate point and vector classes, or just a vector class. Some people swear by separate classes, but in my experience (and I stress that this is only IMX), this approach is rarely used in commercial code or in popular commercial or free math libraries. (I'm sure someone will be able to offer counterexamples - again, I'm just saying that in the math libraries I have studied or used myself this approach has rarely been used).

I've written a lot of code using various math libraries, and I can honestly say that not once have I encountered a case where I wished I had separate point and vector classes available. IMO, this adds a layer of complexity that is unnecessary and unhelpful, and that you just end up having to jump through hoops to work around.

Note that here I'm talking about game development; in a more rigorous mathematical context, having separate point and vector classes might be useful.

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
I'll also just offer my personal opinion on something. Occasionally you'll come across long, spirited discussions online as to whether a math library should have separate point and vector classes, or just a vector class. Some people swear by separate classes, but in my experience (and I stress that this is only IMX), this approach is rarely used in commercial code or in popular commercial or free math libraries. (I'm sure someone will be able to offer counterexamples - again, I'm just saying that in the math libraries I have studied or used myself this approach has rarely been used).

I've written a lot of code using various math libraries, and I can honestly say that not once have I encountered a case where I wished I had separate point and vector classes available. IMO, this adds a layer of complexity that is unnecessary and unhelpful, and that you just end up having to jump through hoops to work around.

Note that here I'm talking about game development; in a more rigorous mathematical context, having separate point and vector classes might be useful.

I'm more familiar with the "rigorous mathematical" environment than with game development, so it should be no surprise that I favor the separate-classes approach. However, I think there are probably practical situations where it would matter. For instance, if you apply an affine transform (say local to world coordinates) to a model where you have vertices (points) and you have normals (vectors), you shouldn't apply the translation part of the transform to the normals, but you should apply everything to the vertices. How is this usually done with libraries that don't distinguish between point and vector?


To the OP: Where is that promised copyright notice? I am afraid you are currently in violation of this code's copyright...

Share this post


Link to post
Share on other sites
Quote:
I'm more familiar with the "rigorous mathematical" environment than with game development, so it should be no surprise that I favor the separate-classes approach. However, I think there are probably practical situations where it would matter. For instance, if you apply an affine transform (say local to world coordinates) to a model where you have vertices (points) and you have normals (vectors), you shouldn't apply the translation part of the transform to the normals, but you should apply everything to the vertices. How is this usually done with libraries that don't distinguish between point and vector?
Sure, you're absolutely right that quite often it does matter. My observation is that the 'point vs. vector' problem is usually solved in one of the following two ways when working with a library that only offers a vector class:

1. Use homogenous coordinates and treat vectors and points uniformly (vectors with a w of 0, points with a w of 1).

2. Provide separate functions for manipulating vectors and points (for example, many libraries have separate 'transform point' and 'transform vector' functions).

There may be other ways to approach the problem, but these are the methods I've seen used most often.

Share this post


Link to post
Share on other sites
Quote:
I wouldn't overload operators ~, * and | for vectors to represent "take a perpendicular", "dot product" and "2D exterior perp product" (I didn't even have a name for this operation), because they are not standard enough, so people will have a hard time understanding code that uses them. I would much rather see functions used for this purpose: `perp(v)', `dot(v,w)' and `exterior_perp_product(v,w)'.
@The OP: I second this. A good rule of thumb: if it's not immediately apparent from context what a particular overload does, use a named function instead. (As with all things there are exceptions, but in the case of basic math classes I think this guideline is applicable.)

Share this post


Link to post
Share on other sites
"How is this usually done with libraries that don't distinguish between point and vector?"

It is traditional that one uses vectors with an "extra" component. A position vector reads [ X Y Z 1 ], a direction vector reads [ X Y Z 0 ]

Transformation matricies contain both the rotation 3x3 matrix and a row of translation -- the zero in the direction matrix means the translation elements are not added in.

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
1. Use homogenous coordinates and treat vectors and points uniformly (vectors with a w of 0, points with a w of 1).

This is a decent solution, but the purist in me would like to point out that homogeneous coordinates with w=0 don't represent vectors: They represent points at infinity. In homogeneous coordinates, [1 0 3 0] and [-2 0 -6 0] represent the same thing.

The arithmetic works, though. It's just the usage of the name "homogeneous coordinates" that bothers me. I should work on it with my therapist. :)

Quote:
2. Provide separate functions for manipulating vectors and points (for example, many libraries have separate 'transform point' and 'transform vector' functions).

This makes sense. You still need to be aware of the difference between points and vectors, and it's simply that the type system doesn't help you.

I guess it's like having separate types for lengths, weights, times, angles... or simply using `float' for everything. In some sense, using a single class for point and vector is a lower-level way of doing things. My intuition is that this would be a good place to use the power of the C++ type system, but if game developers don't see the problem that this would solve, perhaps there isn't one.

Share this post


Link to post
Share on other sites
Firstly, i would like to point out that i didn't write all that code so don't blame me if it's not that great [smile]. In fact, i wasn't going to implement the ~, * and | operators, but i ended up just copying the whole code. I will remove them now, though, as i do agree that should be immediately apparent what overloaded operators do.
Secondly, i personally see the need for separate Point and Vector classes, or at least typedef one as the other. It seems a little silly to use a vector to describe, say, the position of something. Also, arithmetic operations have slightly different meaning on vectors (as you said, * and / aren't well defined on points).
Thirdly, i read that i should put template declaration and definition in the header file, but how do i stop cyclic dependencies? Vector is inherited by Point, but Point uses Vector.
Lastly, if i am going about all this the wrong way, how should i do it?

@alvaro: the copyright says i can freely use it as long as i include that copyright notice. I mentioned in my first post that i have included it in my code (just not in this post).

Share this post


Link to post
Share on other sites
Quote:
Secondly, i personally see the need for separate Point and Vector classes, or at least typedef one as the other. It seems a little silly to use a vector to describe, say, the position of something.
It may seem silly, yet it's done all the time in games and graphics programming. In fact, I don't remember ever seeing a large-scale or commercial game project that used separate point and vector classes (not that there aren't any - I just haven't come across any myself).

Now of course just because a practice is widespread doesn't mean it's correct. Using vectors to represent positions has always seemed ok to me though - I just tend to think of them as a displacement from the origin. It may be though that this isn't defensible from a mathematically rigorous point of view (maybe some of the math experts here could comment on that).

In any case, whether it's technically correct or not, it's certainly common practice to use a single vector class to represent both points and vectors. If you're interested in other views on this subject, check out the book '3D Math Primer for Graphics and Game Development' - the authors devote a section to the topic, and explain why they believe not having a separate point class is both mathematically defensible and more convenient than the alternative.

Share this post


Link to post
Share on other sites
well there is an injection - a one to one correspondence between the points of the (hyper)plane and a set of position vectors in R^n. When people are talking about points and vector spaces they are usually talking about position vectors. Representing them with the same structure makes sense since they are equivalent. except of course when dealing with affine spaces. but that does not change the fact that structurally they are equivalent and when needed the issues of a particular space can be gotten around. e.g. homogeneous coords

Share this post


Link to post
Share on other sites
Quote:
Original post by XTAL256
Firstly, i would like to point out that i didn't write all that code so don't blame me if it's not that great [smile]. In fact, i wasn't going to implement the ~, * and | operators, but i ended up just copying the whole code. I will remove them now, though, as i do agree that should be immediately apparent what overloaded operators do.
Secondly, i personally see the need for separate Point and Vector classes, or at least typedef one as the other. It seems a little silly to use a vector to describe, say, the position of something. Also, arithmetic operations have slightly different meaning on vectors (as you said, * and / aren't well defined on points).
Thirdly, i read that i should put template declaration and definition in the header file, but how do i stop cyclic dependencies? Vector is inherited by Point, but Point uses Vector.
Lastly, if i am going about all this the wrong way, how should i do it?

As I mentioned in my first post, Vector should be implemented without making any reference to Point.

Quote:
@alvaro: the copyright says i can freely use it as long as i include that copyright notice. I mentioned in my first post that i have included it in my code (just not in this post).

But you did post basically all your code, without the copyright notice. I don't think that's acceptable... You can simply go and edit the post, and then there shouldn't be a problem at all.

Share this post


Link to post
Share on other sites
EDIT: Sorry for answering to your post piece by piece. It sounds mean, but I didn't know how else to do it. It is not my intention to be mean. A little smiley will hopefully relax the tone of the post. Here it is: :)

Quote:
Original post by Daerax
well there is an injection - a one to one correspondence between the points of the (hyper)plane and a set of position vectors in R^n.

I am having trouble following the logic here. There is a bijection between the interval [0,1] and R^n, but that doesn't mean that a single number between 0 and 1 is a good representation of an element of R^n.

Quote:
When people are talking about points and vector spaces they are usually talking about position vectors.

No. What I call "vectors" are things that can be added, subtracted and scaled. Positions don't have those properties. But for instance velocities and translations are properly called "vectors".

Quote:
Representing them with the same structure makes sense since they are equivalent.

Except that the operations defined on them are different. You can add two translations (On a plane, move 5m North and 4m East), but you can't add two positions (What position is Vienna + Paris?).

Quote:
except of course when dealing with affine spaces. but that does not change the fact that structurally they are equivalent and when needed the issues of a particular space can be gotten around. e.g. homogeneous coords

Well, we are dealing with affine spaces here. That's the whole point of the discussion.

Share this post


Link to post
Share on other sites
Overloading strange operators for un-related vector ops (or the ops of any class for that matter) is a bad idea. Remember that the operators preserve the normal C++ operator precedence, and your operator selection probably doesn't mirror the operator precedence associated with the mathematical entity you are modeling.

For example, I've seen ^ used as a cross-product operator, but it has one of the lowest precedences -- lower than + and - for instance, meaning that code like a = b + c ^ d doesn't translate as one would expect.

Also, adopting strange symbols means more documentation effort for you, and for your clients.

Share this post


Link to post
Share on other sites
Quote:
Original post by alvaro
EDIT: Sorry for answering to your post piece by piece. It sounds mean, but I didn't know how else to do it. It is not my intention to be mean. A little smiley will hopefully relax the tone of the post. Here it is: :)

Quote:
Original post by Daerax
well there is an injection - a one to one correspondence between the points of the (hyper)plane and a set of position vectors in R^n.

I am having trouble following the logic here. There is a bijection between the interval [0,1] and R^n, but that doesn't mean that a single number between 0 and 1 is a good representation of an element of R^n.

Strawman. There would be no practical value gained from that. Not the case with this correspondence. Everything available in the plane is also in R^2 and in a more tractable format too. The fact is that an element of a vector space R^2 is an Excellent representation of the concept of a point.
Quote:
Quote:
When people are talking about points and vector spaces they are usually talking about position vectors.

No. What I call "vectors" are things that can be added, subtracted and scaled. Positions don't have those properties. But for instance velocities and translations are properly called "vectors".

Yes. We can attack geometric problems with linear algebra for the specific reason that we can rely on that one to one correspondence and in treating the position vectors directly, we can solve geometry problems in a more deft manner. Those position vectors (which is the representation of points many who deal with this stuff actively have in their mind) can be scaled, added, subtracted.

Quote:
Quote:
Representing them with the same structure makes sense since they are equivalent.

Except that the operations defined on them are different. You can add two translations (On a plane, move 5m North and 4m East), but you can't add two positions (What position is Vienna + Paris?).


Irrelevant Conflation. Vienna is not a position, it is at a position. Now, on the plane we can add the position vectors of the two if we fix some origin. Which is what most people are talking about when they talk about points algebraically since really it is the only sensible way.

Quote:

Well, we are dealing with affine spaces here. That's the whole point of the discussion.


In 2D games we don't really act in an affine space. we do what may classify as affine transformations at first but that doesn't mean we have an affine space. there is an implicit coordinate with (0,0) at the top left. What few operations that could classify as affine transforms - the rotations and scaling anywhere - we are still acting in a vector space and simply introducing an origin locally, acting and mapping the result back. We are not actually transforming the screen space or even world space. Scrolling is really an operation on data structures. Even translations could be seen as operations - scaling, additions on a position vector. Those people asking for the angle between two points or the distance between them? They are really talking about vectors.

With that they can say find the distance between two points by subtracting the 'points' and taking the root of the resultant vector dotted with itself. Or skipping the root taking as needed. Just another way to look at it. Points like vectors are an abstract concept with no single meaning, sticking to one meaning regardless of the context and the practicalities at hand is short sited. Becoming attached to a particular definition of a concept in math (or in general!) is like not using the right language for the job. heck, under the right context you can argue a function to be a point.

Bringing up affine spaces and the difference between points and vectors, especially for a 2D game is quite simply.overkill.

Share this post


Link to post
Share on other sites
Quote:
As I mentioned in my first post, Vector should be implemented without making any reference to Point.

I fixed the problems i was having by simply having two separate classes, with vector not inheriting from point. I guess inheritance here is a bit of overkill really, the only thing it is inheriting are the two member variables x and y.

Quote:
Quote:
@alvaro: the copyright says i can freely use it as long as i include that copyright notice. I mentioned in my first post that i have included it in my code (just not in this post).

But you did post basically all your code, without the copyright notice. I don't think that's acceptable... You can simply go and edit the post, and then there shouldn't be a problem at all.

Oh, you mean in this post. Ok, i have edited my initial post and put it in, but only once. The only reason i didn't include it in all 4 source blocks to start with is that it is redundant and annoying to scroll past it to see the code. But I didn't realise it must be included everywhere it is used (even in forum posts).

Quote:
EDIT: Sorry for answering to your post piece by piece. It sounds mean, but I didn't know how else to do it. It is not my intention to be mean. A little smiley will hopefully relax the tone of the post. Here it is: :)

That's ok, i am always open to suggestions (even if i don't always agree with them [smile])

Share this post


Link to post
Share on other sites

This topic is 3044 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this