Sign in to follow this  

vector class

This topic is 4527 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

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

This topic is 4527 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