vector functions

M

Michael Sgier

Hello
If someone could explain the code below to me would be great.

// return angle between two vectors
const float inline Angle(const CVector& normal) const
{
return acosf(*this % normal);
}

// reflect this vector off surface with normal vector
const CVector inline Reflection(const CVector& normal) const
{
const CVector vec(*this | 1); // normalize this vector
return (vec - normal * 2.0 * (vec % normal)) * !*this;
}

// rotate angle degrees about a normal
const CVector inline Rotate(const float angle, const CVector& normal) const
{
const float cosine = cosf(angle);
const float sine = sinf(angle);

return CVector(*this * cosine + ((normal * *this) * (1.0f - cosine)) *
normal + (*this ^ normal) * sine);
}

This is producing the following errors:

vector.h:220: error: declaration does not declare anything
vector.h:220: error: syntax error before `inline'
vector.h:226: error: ISO C++ forbids defining types within return type
vector.h:226: error: syntax error before `inline'
vector.h:233: error: syntax error before `inline'
vector.h:236: error: `angle' was not declared in this scope
vector.h:238: error: syntax error before `return'

What do % and ^ produce? Why is there a const also at the end of the
function definition?
THANKS and regards
Michael
 
C

Christian Meier

Michael Sgier said:
Hello
If someone could explain the code below to me would be great.

// return angle between two vectors
const float inline Angle(const CVector& normal) const
{
return acosf(*this % normal);
}

// reflect this vector off surface with normal vector
const CVector inline Reflection(const CVector& normal) const
{
const CVector vec(*this | 1); // normalize this vector
return (vec - normal * 2.0 * (vec % normal)) * !*this;
}

// rotate angle degrees about a normal
const CVector inline Rotate(const float angle, const CVector& normal) const
{
const float cosine = cosf(angle);
const float sine = sinf(angle);

return CVector(*this * cosine + ((normal * *this) * (1.0f - cosine)) *
normal + (*this ^ normal) * sine);
}

This is producing the following errors:

vector.h:220: error: declaration does not declare anything
vector.h:220: error: syntax error before `inline'
vector.h:226: error: ISO C++ forbids defining types within return type
vector.h:226: error: syntax error before `inline'
vector.h:233: error: syntax error before `inline'
vector.h:236: error: `angle' was not declared in this scope
vector.h:238: error: syntax error before `return'

Paste your whole class. Or better: Reduce your code as much as possible and
then paste your class here.
What do % and ^ produce?

% is the modulus operator. It returns the remainder of a division.
^ is the bitwise-exclusive-or operator. It compares each bit. If one of them
is 0 and the other one is 1, the corresponding bit in the result is also 1,
otherwise it is 0.
Why is there a const also at the end of the
function definition?

Functions of a class are not allowed to modify the member variables if a
function was declared as const.
THANKS and regards
Michael

Greetings Chris
 
K

Kai-Uwe Bux

Christian said:
Paste your whole class. Or better: Reduce your code as much as possible
and then paste your class here.


% is the modulus operator. It returns the remainder of a division.
^ is the bitwise-exclusive-or operator. It compares each bit. If one of
them is 0 and the other one is 1, the corresponding bit in the result is
also 1, otherwise it is 0.

Well, I am inclined to bet that these operators are overloaded in that
vector class to compute the scalar product and the cross product, and I
also suspect that operator! has been tweaked to compute the norm of the
vector and that operator| rescales a vector to a given length.


Best

Kai-Uwe Bux
 
P

persenaama

/*
const float inline Angle(const CVector& normal) const
{
return acosf(*this % normal);
}
*/

Above the % should be scalar product so that the angle between *this
and normal would be computed, it's generally a bad to use % for cross
product, which it is often seen used in code like this. Using it for
dot/scalar product is even more strange.

Just commenting on that oddity, I could comment on the errors if I knew
which line was which (eg. which error correspond to which line). I bet
somewhere along the line some declaration was missed (maybe the headers
are not self-contained or require specific order of inclusion,
whatever, beats me w/o seeing more of the code.. :)
 
P

persenaama

I just cannot resisting replying again.. I keep staring at the code in
disbelief: really bizarre use of operator overloading. +, -, /, * ..
are are still cool and useful since the meaning is easily understood,
but... what is happening here is beyond belief.. incredible stuff.. no
offence! 8P
 
R

Richard Herring

This appears to be a member function. So what's the declaration of the
class of which it's a member? We're not mind-readers here.

So which of the above is line 220? We're not mind-readers here.
Paste your whole class. Or better: Reduce your code as much as possible and
then paste your class here.


% is the modulus operator. It returns the remainder of a division.
^ is the bitwise-exclusive-or operator. It compares each bit. If one of them
is 0 and the other one is 1, the corresponding bit in the result is also 1,
otherwise it is 0.

Not quite. % and ^ applied to built-in types do as you say. Here the
operands are of type CVector, whatever that is. My guess is that the
author of the class CVector has overloaded those operators (and also
operator| and operator*) to make them perform some completely unrelated
function.

Which is, of course, *EVIL*.
 
K

Kai-Uwe Bux

Richard said:
Christian Meier said:
// reflect this vector off surface with normal vector
const CVector inline Reflection(const CVector& normal) const
{
const CVector vec(*this | 1); // normalize this vector
return (vec - normal * 2.0 * (vec % normal)) * !*this;
}

// rotate angle degrees about a normal
const CVector inline Rotate(const float angle, const CVector& normal) const
{
const float cosine = cosf(angle);
const float sine = sinf(angle);

return CVector(*this * cosine + ((normal * *this) * (1.0f - cosine)) *
normal + (*this ^ normal) * sine);
}
[snip]
% is the modulus operator. It returns the remainder of a division.
^ is the bitwise-exclusive-or operator. It compares each bit. If one of
them is 0 and the other one is 1, the corresponding bit in the result is
also 1, otherwise it is 0.

Not quite. % and ^ applied to built-in types do as you say. Here the
operands are of type CVector, whatever that is. My guess is that the
author of the class CVector has overloaded those operators (and also
operator| and operator*) to make them perform some completely unrelated
function.

Which is, of course, *EVIL*.


I beg to differ. It is not evil; it is the legitimate attempt to make the
math in your code resemble the math from your text book as closely as
possible. This, makes it indeed easier to maintain the code (after some
learning curve). The fact that one can actually guess what the operators in
the OPs code are doing supports this hypothesis:

CVector operator| ( double length ) const;
// rescale a vector to length

double operator% ( CVector const & other ) const;
// scalar product

double operator! ( void ) const;
// norm

CVector operator^ ( CVector const & other ) const;
// cross product

[operator* appears to denote a projection, and I have to admit that the use
of an operator for this is questionable as you usually will not find infix
notation for projections in math texts.]


Whether operator overloading is moral or evil is a cultural question, and
the correct answer is very much context dependent. Operator overloading in
C++ allows you to implement special purpose sublanguages. Admittedly, this
is a double edged sword. In the context of math programming, I find it by
and large very helpful.


Best

Kai-Uwe Bux
 
C

Christian Meier

Kai-Uwe Bux said:
Well, I am inclined to bet that these operators are overloaded in that
vector class to compute the scalar product and the cross product, and I
also suspect that operator! has been tweaked to compute the norm of the
vector and that operator| rescales a vector to a given length.

Of course they are overloaded. Well not "of course", but I am quite sure,
too. Fact is, we do not have any code. Another fact is, that the source
above does not compile.
So, without more code and without guesses the operators want to do, what I
described.
If he wants to know what does operator do with *this, he has to paste more
code of the class, as I mentioned. OK, where do we know if this code is
inside a class? The keyword inline is a bit confusing. It would not be
necessary if this were a class....

Anyway, to be sure, we need more code.
Best

Kai-Uwe Bux

Greetings Chris
 
M

Michael Sgier

Hello again
here's more code with the copyright. I've cutted out the parts that
i've believed to have understood. I would be very grateful for any
explanations on the following especially where i marked my questions.
( and of course the resolving of the errors. The error messages were put
to the corresponding line where
they appeared to the end of the code. )
THANKS and regards
Michael


#ifndef __VECTOR_H
#define __VECTOR_H

#include <math.h>

/*
VECTOR.H

CVector class

Some operators of the CVector class based on
operators of the CVector class by Bas Kuenen.
Copyright (c) 2000 Bas Kuenen. All Rights Reserved.
homepage: baskuenen.cfxweb.net
*/

#define PI (3.14159265359f)
#define DEG2RAD(a) (PI/180*(a))
#define RAD2DEG(a) (180/PI*(a))

typedef float scalar_t;

class CVector
{
public:
scalar_t x;
scalar_t y;
scalar_t z; // x,y,z coordinates

public:
CVector(scalar_t a = 0, scalar_t b = 0, scalar_t c = 0) : x(a),
y(b), z(c) {} // what does the : here?
CVector(const CVector &vec) : x(vec.x), y(vec.y), z(vec.z) {}

// vector index
scalar_t &operator[](const long idx)
{
return *((&x)+idx);
}

// vector assignment
const CVector &operator=(const CVector &vec) // I don't really
understand: (const CVector &vec) ???
{
x = vec.x;
y = vec.y;
z = vec.z;

return *this;
}

// vector add
const CVector operator+(const CVector &vec) const
{
return CVector(x + vec.x, y + vec.y, z + vec.z);
}

// vector add (opposite of negation)
const CVector operator+() const // hmmmm???? same to
the following ones
{
return CVector(*this);
}


// scalar self-divecide
const CVector &operator/=(const scalar_t &s)
{
const float recip = 1/s; // for speed, one divecision

x *= recip;
y *= recip;
z *= recip;

return *this;
}

// pre multiply by scalar
friend inline const CVector operator*(const scalar_t &s, const
CVector &vec)
{
return vec*s;
}

const CVector operator*(const CVector& vec) const
{
return CVector(x*vec.x, y*vec.y, z*vec.z);
}

// post multiply by scalar
/*friend inline const CVector operator*(const CVector &vec, const
scalar_t &s)
{
return CVector(vec.x*s, vec.y*s, vec.z*s);
}*/

// divide by scalar
const CVector operator/(scalar_t s) const
{
s = 1/s;

return CVector(s*x, s*y, s*z);
}

// dot product
const scalar_t DotProduct(const CVector &vec) const
{
return x*vec.x + y*vec.x + z*vec.z;
}

// dot product
const scalar_t operator%(const CVector &vec) const // why two
functions?
{
return x*vec.x + y*vec.x + z*vec.z;
}

// normalize this vector
void Normalize()
{
(*this) /= Length(); //humm???
}

const scalar_t operator!() const // why "const
CVector &vec" was omitted?
{
return sqrtf(x*x + y*y + z*z);
}

// return vector with specified length
const CVector operator | (const scalar_t length) const
{
return *this * (length / !(*this));
}

// set length of vector equal to length
const CVector& operator |= (const float length)
{
return *this = *this | length; // what's the
| here?
}

// return angle between two vectors
//those errors here at next line
//vector.h:220: error: declaration does not declare anything
//vector.h:220: error: syntax error before `inline'
const float inline Angle(const CVector& normal) const
{
return acosf(*this % normal);
}

// reflect this vector off surface with normal vector
//those errors here at next line
//vector.h:226: error: ISO C++ forbids defining types within return type
//vector.h:226: error: syntax error before `inline'

const CVector inline Reflection(const CVector& normal) const
{
const CVector vec(*this | 1); // normalize this vector
return (vec - normal * 2.0 * (vec % normal)) * !*this;
}

// rotate angle degrees about a normal
//those errors here at next line
//vector.h:233: error: syntax error before `inline'
const CVector inline Rotate(const float angle, const CVector& normal) const
{
const float cosine = cosf(angle);
//those errors here at next line
//vector.h:236: error: `angle' was not declared in this scope
const float sine = sinf(angle);
//those errors here at next line
//vector.h:238: error: syntax error before `return'
return CVector(*this * cosine + ((normal * *this) * (1.0f - cosine)) *
normal + (*this ^ normal) * sine);
}
};

#endif
 
J

John Harrison

Michael said:
Hello again
here's more code with the copyright. I've cutted out the parts that
i've believed to have understood. I would be very grateful for any
explanations on the following especially where i marked my questions.
( and of course the resolving of the errors. The error messages were put
to the corresponding line where
they appeared to the end of the code. )

Comments follow
THANKS and regards
Michael


#ifndef __VECTOR_H
#define __VECTOR_H

#include <math.h>

/*
VECTOR.H

CVector class

Some operators of the CVector class based on
operators of the CVector class by Bas Kuenen.
Copyright (c) 2000 Bas Kuenen. All Rights Reserved.
homepage: baskuenen.cfxweb.net
*/

#define PI (3.14159265359f)
#define DEG2RAD(a) (PI/180*(a))
#define RAD2DEG(a) (180/PI*(a))

typedef float scalar_t;

class CVector
{
public:
scalar_t x;
scalar_t y;
scalar_t z; // x,y,z coordinates

public:
CVector(scalar_t a = 0, scalar_t b = 0, scalar_t c = 0) : x(a),
y(b), z(c) {} // what does the : here?
CVector(const CVector &vec) : x(vec.x), y(vec.y), z(vec.z) {}

// vector index
scalar_t &operator[](const long idx)
{
return *((&x)+idx);
}

// vector assignment
const CVector &operator=(const CVector &vec) // I don't really
understand: (const CVector &vec) ???

This is standard. It says that the assignment operator for CVectors
takes one argument by reference (& means by reference), and does not use
that reference to alter the argument (that's what const means). This is
what you would want from an assignment operator. Also notice that the
copy constructor above is similar for similar reasons.
{
x = vec.x;
y = vec.y;
z = vec.z;

return *this;
}

// vector add
const CVector operator+(const CVector &vec) const
{
return CVector(x + vec.x, y + vec.y, z + vec.z);
}

// vector add (opposite of negation)
const CVector operator+() const // hmmmm???? same to
the following ones

What's to hmmm? Again we have a const member function returning a const
object. The member function is const because it does not alter the
object. The return is const because if it were not then this code

CVector v1, v2;
+v1 = v2;

would be legal. It's not a big issue because you would probably never
write code like that, but I'm sure you agree there no harm in
disallowing code like that.
{
return CVector(*this);
}


// scalar self-divecide
const CVector &operator/=(const scalar_t &s)
{
const float recip = 1/s; // for speed, one divecision

x *= recip;
y *= recip;
z *= recip;

return *this;
}

// pre multiply by scalar
friend inline const CVector operator*(const scalar_t &s, const
CVector &vec)
{
return vec*s;
}

const CVector operator*(const CVector& vec) const
{
return CVector(x*vec.x, y*vec.y, z*vec.z);
}

// post multiply by scalar
/*friend inline const CVector operator*(const CVector &vec, const
scalar_t &s)
{
return CVector(vec.x*s, vec.y*s, vec.z*s);
}*/

// divide by scalar
const CVector operator/(scalar_t s) const
{
s = 1/s;

return CVector(s*x, s*y, s*z);
}

// dot product
const scalar_t DotProduct(const CVector &vec) const
{
return x*vec.x + y*vec.x + z*vec.z;
}

// dot product
const scalar_t operator%(const CVector &vec) const // why two
functions?
{
return x*vec.x + y*vec.x + z*vec.z;
}

Good question. Drop the operator% would be my advice.
// normalize this vector
void Normalize()
{
(*this) /= Length(); //humm???
}

Seems reasonable to me, divide a vector by it's length, resulting is a
vector of length 1. What's the problem?
const scalar_t operator!() const // why "const
CVector &vec" was omitted?
{
return sqrtf(x*x + y*y + z*z);
}

Because operator! operates on a single CVector, not two CVector's.
// return vector with specified length
const CVector operator | (const scalar_t length) const
{
return *this * (length / !(*this));
}

// set length of vector equal to length
const CVector& operator |= (const float length)
{
return *this = *this | length; // what's the |
here?
}

It calls the function declared immediately above this one. The one with
the comment 'return vector with specified length'.

In general if you define operator@ you should also define operator @=,
this is what is being done here. operator| is defined then operator|= is
defined so that is calls operator|.

// return angle between two vectors
//those errors here at next line
//vector.h:220: error: declaration does not declare anything
//vector.h:220: error: syntax error before `inline'
const float inline Angle(const CVector& normal) const
{
return acosf(*this % normal);
}

inline is illegal here, remove it. Should be fine then.
// reflect this vector off surface with normal vector
//those errors here at next line
//vector.h:226: error: ISO C++ forbids defining types within return type
//vector.h:226: error: syntax error before `inline'

const CVector inline Reflection(const CVector& normal) const
Ditto.

{
const CVector vec(*this | 1); // normalize this vector
return (vec - normal * 2.0 * (vec % normal)) * !*this;
}

// rotate angle degrees about a normal
//those errors here at next line
//vector.h:233: error: syntax error before `inline'
const CVector inline Rotate(const float angle, const CVector&
normal) const
Ditto.

{
const float cosine = cosf(angle);
//those errors here at next line
//vector.h:236: error: `angle' was not declared in this scope
const float sine = sinf(angle);
//those errors here at next line
//vector.h:238: error: syntax error before `return'
return CVector(*this * cosine + ((normal * *this) * (1.0f -
cosine)) *
normal + (*this ^ normal) * sine);
}
};

#endif

john
 
J

John Harrison

It's pretty clear that operator overloading is a bit of a mystery to
you. But there is no mystery, overloaded operators are just function
calls with a different syntax. That is pretty much all there is to it.

CVector a , b, c;

a + b; // call overloaded + operator (two parameters)
!a; // call overloaded ! operator (one parameter)
a = b; // call overloaded = operator (two parameters)
c = a % b; // call overloaded % operator, which returns a result, which
is then used as a parameter to the overloaded = operator.

In the above +, !, = and % are just functions (or member functions).

john
 
C

Christian Meier

John Harrison said:
Comments follow

Seems that you did not see this question.

In constructors you have an initializer part.
After
CVector() : x(0) {}
you have the same as after
CVector() { x = 0; }

In your constructor CVector(scalar_t a = 0, scalar_t b = 0, scalar_t c = 0)
you have three default arguments. So, if you instantiate CVector without
arguments, then your x, y and z are 0.

The rest was answered.

Greetings Chris
 
K

Karl Heinz Buchegger

John said:
It's pretty clear that operator overloading is a bit of a mystery to
you. But there is no mystery, overloaded operators are just function
calls with a different syntax. That is pretty much all there is to it.

CVector a , b, c;

a + b; // call overloaded + operator (two parameters)
!a; // call overloaded ! operator (one parameter)
a = b; // call overloaded = operator (two parameters)
c = a % b; // call overloaded % operator, which returns a result, which
is then used as a parameter to the overloaded = operator.

In the above +, !, = and % are just functions (or member functions).

To the OP:

It becomes clearer this way:

a + b

is equivalent to (if the operator is a member function of the class)

a.operator+( b )

Here one can see the function call explicitely.

If the operator is a freestanding function, then the above becomes:

operator+( a, b );

Another example:
c = a + b;
with all operators as member functions:
c.operator=( a.operator+( b ) );
or a free standing operator+
c.operator=( operator+( a, b ) );

Don't let yourself fool you with that special word 'operator'. They are just
ordinary functions which can be used in a special 'call syntax' ( a + b instead
of a.foo( b ) ).
 
R

Richard Herring

Kai-Uwe Bux said:
Richard said:
Christian Meier said:
news:[email protected]... [snip]
// reflect this vector off surface with normal vector
const CVector inline Reflection(const CVector& normal) const
{
const CVector vec(*this | 1); // normalize this vector
return (vec - normal * 2.0 * (vec % normal)) * !*this;
}

// rotate angle degrees about a normal
const CVector inline Rotate(const float angle, const CVector& normal)
const
{
const float cosine = cosf(angle);
const float sine = sinf(angle);

return CVector(*this * cosine + ((normal * *this) * (1.0f - cosine)) *
normal + (*this ^ normal) * sine);
} [snip]
% is the modulus operator. It returns the remainder of a division.
^ is the bitwise-exclusive-or operator. It compares each bit. If one of
them is 0 and the other one is 1, the corresponding bit in the result is
also 1, otherwise it is 0.

Not quite. % and ^ applied to built-in types do as you say. Here the
operands are of type CVector, whatever that is. My guess is that the
author of the class CVector has overloaded those operators (and also
operator| and operator*) to make them perform some completely unrelated
function.

Which is, of course, *EVIL*.


I beg to differ. It is not evil; it is the legitimate attempt to make the
math in your code resemble the math from your text book as closely as
possible.

As closely as possible, certainly. But not more so :-(
This, makes it indeed easier to maintain the code (after some
learning curve). The fact that one can actually guess what the operators in
the OPs code are doing supports this hypothesis:

CVector operator| ( double length ) const;
// rescale a vector to length

I've never seen a special mathematical notation for that. The only clue
is in the argument name, which is only visible in the declaration of the
function, not its use. IMO a suitably-named function would be clearer.

(Moreover I suspect that the right-hand operand will almost always be 1,
in which case why not use operator~ to suggest the "hat" notation for
taking a unit vector?)
double operator% ( CVector const & other ) const;
// scalar product

Granted, operator. can't be overloaded, so some other symbol is needed,
but there's nothing transparent about using something suggesting
"remainder" for multiplication, especially as operator* would be the
obvious choice.
double operator! ( void ) const;
// norm

Hmm. If that's meant to suggest the |a| notation it's ambiguous: norm or
abs? Personally I'd take a hint from the implementation of std::complex
and go for a function called norm.
CVector operator^ ( CVector const & other ) const;
// cross product

Fair enough. That, like + and -, matches the mathematical notation.
[operator* appears to denote a projection, and I have to admit that the use
of an operator for this is questionable as you usually will not find infix
notation for projections in math texts.]

Quite. The natural interpretation of * is a product, and as ^ naturally
suggests cross product, I'd expect this to give the "other" product,
i.e. the scalar one.
Whether operator overloading is moral or evil is a cultural question, and
the correct answer is very much context dependent. Operator overloading in
C++ allows you to implement special purpose sublanguages. Admittedly, this
is a double edged sword. In the context of math programming, I find it by
and large very helpful.
I think we must agree to differ. By all means overload operators if the
operation is broadly the same as their conventional meaning, but if
you're torturing the syntax by overloading an operator only because it
isn't otherwise used and happens to have the right syntax, it's time to
start thinking of sensibly-named functions.
 
J

John Harrison

Seems that you did not see this question.

Right I didn't. Seems to me that the OP is trying to write a substantial
C++ program (or at least modify one) and hoping to learn C++ as they go
along. I wouldn't wnat to discourage that (each to their own etc.) but a
little simultaneous background reading wouldn't go amiss. Try to adsorb
a few of the basic concepts and constructs of C++.

john
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top