Sign in to follow this  
mike74

vector class

Recommended Posts

I would like to make a class for 3d vectors, and I would like it to feature the dot product and cross product operations. Ideally, I would like to do them using operator overloading, but it seems there's no real intuitive way of doing this. I suppose I could use the * operator for the cross product and the . operator for the dot product, but overloading the . like that could be really confusing. Has anyone found an intuitive way to support both dot and cross product with operators in C++? Mike C. http://www.coolgroups.com/

Share this post


Link to post
Share on other sites
Quote:
Original post by mike74
Has anyone found an intuitive way to support both dot and cross product with operators in C++?


Overloading the * operator for cross product may get confusing, depending on how you implement your scalar multiplication. Consider this:

v1 = v2 * v3 * scalar

At first glance, there's 2 multiplications occuring. This can get more confusing as your equation's complexity rises. The alternatives would be a Vector3D::Cross( const Vector3D * ) method or a stand-alone function:

v1 = v2.Cross( &v3 ) * scalar

v1 = Cross3D( &v2, &v3 ) * scalar

both of which are a little unruly. Intuitively, I'd use '*' for dot product and 'x' for cross product. Conceptually, since they're both symbolic of an equation, I'd use the stand alone function.

To answer your question, I haven't found an intuitive way to handle both of these equations using operators - maybe somebody else has.

:stylin:

Share this post


Link to post
Share on other sites
All the people I trust say "use named member functions" on this one. A multiplication isn't obviously either dot or cross, '.' can't be overloaded, 'x' isn't even an operator, and anything else is just a ridiculous abuse. Besides, operations involving more than one (dot or cross) product in a row are rare, and with more than two are practically unheard of, so the normal syntax of member functions - or even of free functions - really isn't awkward here.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
If you really want to have operators for these, you can overload '%' as dot product and '^' as cross-product. They're not very intuitive but keep operator priority.

Share this post


Link to post
Share on other sites
I would prefer to use non-member functions for dot and cross product. Some people consider using member functions to be more intuitive; however, just as many consider using member functions to be counter intuitive as they may appear to be mutators of the object on the left hand side.

On the whole, I would recomment against overloading unrelated operators to provide the dot or cross product as operators already have a sense of built in meaning.

There are additional (bad) ways of handling this. One of my favorite bad methods goes like:

class Vector {
public:
Vector(float x = 0.0f, float y = 0.0f, float z = 0.0f)
: x_(x), y_(y), z_(z)
{}

public:
float x_;
float y_;
float z_;
};

template <typename Op>
struct LtProxy {
LtProxy(const Vector & r) : ref_(r) {}
const Vector & ref_;
};

const struct DotT {} dot;

LtProxy<DotT> operator<(const Vector & lhs, const DotT & rhs) {
return LtProxy<DotT>(lhs);
}

float operator>(const LtProxy<DotT> & lhs, const Vector & rhs) {
return ( (lhs.ref_.x_ * rhs.x_) +
(lhs.ref_.y_ * rhs.y_) +
(lhs.ref_.z_ * rhs.z_) );
}

const struct CrossT {} cross;

LtProxy<CrossT> operator<(const Vector & lhs, const CrossT & rhs) {
return LtProxy<CrossT>(lhs);
}

Vector operator>(const LtProxy<CrossT> & lhs, const Vector & rhs) {
return Vector( (lhs.ref_.y_ * rhs.z_ - lhs.ref_.z_ * rhs.y_),
(lhs.ref_.z_ * rhs.x_ - lhs.ref_.x_ * rhs.z_),
(lhs.ref_.x_ * rhs.y_ - lhs.ref_.y_ * rhs.x_) );
}

int main(int, char **) {
Vector a(0, 1, 3);
Vector b(4, 2, 1);

float dot_product = a <dot> b;
std::cout << dot_product << std::endl;

Vector cross_product = a <cross> b;
std::cout << cross_product.x_ << std::endl;
std::cout << cross_product.y_ << std::endl;
std::cout << cross_product.z_ << std::endl;

return 0;
}


This abuses the associativity of relational operators and operator overloading in general, is unmaintainable and can give operator precdence headaches, but it's fun.

Of course, I have a slightly twisted definition of fun.

Share this post


Link to post
Share on other sites
Irrlicht engine, a 3d API that I'm currently working with, uses named member functions for both dot- and cross-product. I'd suggest, however, to use a non-member function (but within a namespace) or a static member function of Vector. Either of these methods would help you to stick with a good OO approach.

Vector3D cp = Vector3D::CrossProduct(vector1, vector2);
float dp = Vector3D::DotProduct(vector1, vector2);

Share this post


Link to post
Share on other sites
Err, yes, I wasn't recalling quite properly when I wrote "named member functions". Good points, guys. :)

Share this post


Link to post
Share on other sites

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