Creating scalar multiplication operator for 2d vector class - c++

So I'm making a 2D vector class for a class where I create collisions between circular objects with mass and radius on a x-y plane. So everytime a collision happens, I need to update the velocity of the two circles that collided and this relies upon scalar numbers like mass and radius as well as the kinetic energy (scalar) and the momentum (2d vector) of the stones (since momentum and energy conserved , you can solve the momentum and energy of either). All the methods work except for the scalar multiplication. I will only display that method below unless you guys specifically request for me to show the others
Here's my 2d vector class
class vector2d {
public:
double x;
double y;
// Constructor
vector2d() { x=0; y=0; }
vector2d(double_x, double_y) { x=_x; y=_y;}
.
.
.
vector2d operator*(const double& scalar) const {
return {x * scalar, y * scalar };
}
Here's the method in the other class that does the updates the velocity after collision
void collide(Ball *s) {
// Make sure move is called before this to update the position vector'
vec2d diff_pos_s1 = this->init_pos - s->init_pos;
vec2d diff_vel_s1 = this->velocity - s->velocity;
double mass_ratio_s1 = (2 * s->mass) / (this->mass + s->mass);
double num_s1 = diff_pos_s1.dot_product(diff_vel_s1);
double denom_s1 = diff_pos_s1.dot_product(diff_pos_s1);
vec2d v1 = this->velocity - (mass_ratio_s1 * (num_s1 / denom_s1) * diff_pos_s1);
vec2d diff_pos_s2 = s->init_pos - this->init_pos;
vec2d diff_vel_s2 = s->velocity - this->velocity;
double mass_ratio_s2 = (2 * this->mass) / (this->mass + s->mass);
double num_s2 = diff_vel_s2.dot_product(diff_pos_s2);
double denom_s2 = diff_pos_s2.dot_product(diff_pos_s2);
vec2d v2 = s->velocity - (mass_ratio_s2 * (num_s2 / denom_s2) * diff_pos_s2);
this->velocity = v1;
s->velocity = v2;
}
Here's the methods that calculate energy and momentum
double energy() const {
return 0.5 * (mass * velocity * velocity) ;
}
// Calculates the momentum of the balls
vec2d momentum() const {
return mass * velocity;
}
Here are the errors that are produced:
error: no match for 'operator*' (operand types are 'double' and 'vector2d')
error: no match for 'operator*' (operand types are 'const double' and 'vector2d')
Let me know if I should put more information

Your code multiples a double to a vector2d. That won't activate the operator, because the operator will expect a vector2d first. You should have either
vec2d v1 = this->velocity - (diff_pos_s1 * (mass_ratio_s1 * (num_s1 / denom_s1)));
or write an vector2d operator*(double, vector2d), for instance
vector2d operator *(const double & scalar, const vector2d & other) {
return { other.x * scalar, other.y*scalar };
}
As an aside, it seems a waste of time to me to use a reference on a const double.

Related

How to, given UV on a triangle, find XYZ?

I have a triangle, each point of which is defined by a position (X,Y,Z) and a UV coordinate (U,V):
struct Vertex
{
Vector mPos;
Point mUV;
inline Vector& ToVector() {return mPos;}
inline Vector& ToUV() {return mUV;}
};
With this function, I am able to get the UV coordinate at a specific XYZ position:
Point Math3D::TriangleXYZToUV(Vector thePos, Vertex* theTriangle)
{
Vector aTr1=theTriangle->ToVector()-(theTriangle+1)->ToVector();
Vector aTr2=theTriangle->ToVector()-(theTriangle+2)->ToVector();
Vector aF1 = theTriangle->ToVector()-thePos;
Vector aF2 = (theTriangle+1)->ToVector()-thePos;
Vector aF3 = (theTriangle+2)->ToVector()-thePos;
float aA=aTr1.Cross(aTr2).Length();
float aA1=aF2.Cross(aF3).Length()/aA;
float aA2=aF3.Cross(aF1).Length()/aA;
float aA3=aF1.Cross(aF2).Length()/aA;
Point aUV=(theTriangle->ToUV()*aA1)+((theTriangle+1)->ToUV()*aA2)+((theTriangle+2)->ToUV()*aA3);
return aUV;
}
I attempted to reverse-engineer this to make a function that gets the XYZ coordinate from a specific UV position:
Vector Math3D::TriangleUVToXYZ(Point theUV, Vertex* theTriangle)
{
Point aTr1=theTriangle->ToUV()-(theTriangle+1)->ToUV();
Point aTr2=theTriangle->ToUV()-(theTriangle+2)->ToUV();
Point aF1 = theTriangle->ToUV()-theUV;
Point aF2 = (theTriangle+1)->ToUV()-theUV;
Point aF3 = (theTriangle+2)->ToUV()-theUV;
float aA=gMath.Abs(aTr1.Cross(aTr2)); // NOTE: Point::Cross looks like this: const float Cross(const Point &thePoint) const {return mX*thePoint.mY-mY*thePoint.mX;}
float aA1=aF2.Cross(aF3)/aA;
float aA2=aF3.Cross(aF1)/aA;
float aA3=aF1.Cross(aF2)/aA;
Vector aXYZ=(theTriangle->ToVector()*aA1)+((theTriangle+1)->ToVector()*aA2)+((theTriangle+2)->ToVector()*aA3);
return aXYZ;
}
This works MOST of the time. However, it seems to exponentially "approach" the right-angled corner of the triangle-- or something. I'm not really sure what's going on except that the result gets wildly inaccurate the closer it gets to the right-angle.
What do I need to do to this TriangleUVtoXYZ function to make it return accurate results?
I haven't tested your implementation, but you only need to compute two parametric coordinates - the third being redundant since they should sum to 1.
Vector Math3D::TriangleUVToXYZ(Point theUV, Vertex* theTriangle)
{
// T2-T1, T3-T1, P-T1
Point aTr12 = theTriangle[1].ToUV() - theTriangle[0].ToUV();
Point aTr13 = theTriangle[2].ToUV() - theTriangle[0].ToUV();
Point aP1 = theUV - theTriangle[0].ToUV();
// don't need Abs() for the denominator
float aA23 = aTr12.Cross(aTr13);
// parametric coordinates [s,t]
// s = (P-T1)x(T2-T1) / (T3-T1)x(T2-T1)
// t = (P-T1)x(T3-T1) / (T2-T1)x(T3-T1)
float aA12 = aP1.Cross(aTr12) / -aA23;
float aA13 = aP1.Cross(aTr13) / aA23;
// XYZ = V1 + s(V2-V1) + t(V3-V1)
return theTriangle[0].ToVector()
+ aA12 * (theTriangle[1].ToVector() - theTriangle[0].ToVector())
+ aA13 * (theTriangle[2].ToVector() - theTriangle[0].ToVector());
}

Why is my vector rotation function changing the vector's magnitude?

I'm looking to make a simple function that rotates a vector's point b around point a for a given number of degrees.
What's odd is that my code seems to work somewhat - the vector is rotating, but it's changing length pretty drastically.
If I stop erasing the screen every frame to see every frame at once, I see the lines producing a sort of octagon around my origin.
Even weirder is that the origin isn't even in the center of the octagon - it's in the bottom left.
Here's my code:
struct Point { int x, y; };
struct Line {
Point a, b;
void rotate(double);
};
void Line::rotate(double t)
{
t *= 3.141592 / 180;
double cs = cos(t);
double sn = sin(t);
double trans_x = (double)b.x - a.x;
double trans_y = (double)b.y - a.y;
double newx = trans_x * cs - trans_y * sn;
double newy = trans_x * sn + trans_y * cs;
newx += a.x;
newy += a.y;
b.x = (int)newx;
b.y = (int)newy;
}
Using the olc::PixelGameEngine to render, which is why I'm using ints to store coordinates.

C++/SDL angle from one object to another

I want to rotate a 2-D image in the direction to where I click, to all quadrants. To do this, I need to calculate the angle relative to the object. I need 2 vectors.
I have tried to do this: one vector would be the "click" point, the other would be an "imaginary" horizontal vector departing from the object with the same X as the "click" point but with the Y of the object. That would serve as the second vector to where I would calculate the angle from the object.
I have made a test program with 3 objects to see if I can get those angles. b6 is the object, b7 is a "click point" approximately 45º from b6, and b8 is another "click point" approximately 135º from b6.
This is the code I'm using:
#define PI 3.14159265
int main(int argc, char** argv) {
Button b6(100,100);
Button b7(150,50);
Button b8(150,150);
int dot1 = b7.getX() * b7.getX() + b7.getY() * b6.getY();
int det1 = b7.getX() * b6.getY() - b7.getY() * b7.getX();
double angle1 = atan2(det1,dot1)* 180/PI;
int dot2 = b8.getX() * b8.getX() + b8.getY() * b6.getY();
int det2 = b8.getX() * b6.getY() - b8.getY() * b8.getX();
double angle2 = atan2(det2,dot2)* 180/PI;
}
The results don't correspond to the actual position of b7 and b8. angle1 is 15.25, and angle2 is -11.31.
I'm a novice in this, and I don't know if what I'm doing is a total mess. Can anyone help me compute these angles?
As Sam already wrote in comment – not clear, what OP wants to achieve with dot and det. It sounds a bit like dot product but it's not necessary here.
A vector from one point to the other is simply the subtraction of points (point vectors).
Subtraction of point vectors is simply the subtraction of vector components.
Using the components of these vectors in atan2() provides the slope of these vectors:
#include <iostream>
#include <cmath>
const double Pi = 3.14159265;
struct Vec2 {
const double x, y;
Vec2(double x, double y): x(x), y(y) { }
~Vec2() = default;
Vec2(const Vec2&) = default;
Vec2& operator=(const Vec2&) = delete;
};
int main()
{
const Vec2 b6(100, 100);
const Vec2 b7(150, 50);
const Vec2 b8(150, 150);
// vector b6->b7
const Vec2 b67(b7.x - b6.x, b7.y - b6.y);
// vector b6->b8
const Vec2 b68(b8.x - b6.x, b8.y - b6.y);
// slope b67
const double angle1 = atan2(b67.y, b67.x) * 180 / Pi;
// slope b68
const double angle2 = atan2(b68.y, b68.x) * 180 / Pi;
// output
std::cout
<< "angle1: " << angle1 << '\n'
<< "angle2: " << angle2 << '\n';
// done
return 0;
}
Output:
angle1: -45
angle2: 45
Live Demo on coliru
A Sketch of the Vec2 instances:

Calculate bounce angle aggainst rotated line

I have been trying to implement The second answer of this question
My variables are mainly named the same as in the link.
Here they calculate the bounce angle of a point on a rotated surface with normals,
But I can't seem to do it, am I doing something wrong?
The value output I'm expecting is the new velocity after bouncing on the rotated line, currently my output is doing all crazy kind of things, bouncing to high, bouncing the other way and sometimes the right way but mostly ignoring the rotated angle of my line.
Here's my current Code:
Variables:
Top is the first point of my line
Right is the second point of my line
n is the normal
v is the velocity
dotv is n * v
dotn is n * n
Old Code:
sf::Vector2f n(-(top.y - right.y),(top.x - right.x));
sf::Vector2f dotv = sf::Vector2f(ball.getSpeed().x * n.x, ball.getSpeed().y * n.y);
sf::Vector2f dotn = sf::Vector2f(n.x*n.x,n.y*n.y);
sf::Vector2f u = sf::Vector2f(dotv.x/dotn.x,dotv.y/dotn.y);
u = sf::Vector2f(u.x*n.x,u.y*n.y);
sf::Vector2f w = ball.getSpeed() - u;
ball.setSpeed(sf::Vector2f((sf::Vector2f(w.x*0.5,w.y*0.5)-u)));
Edit:
New Code:
sf::Vector2f n(-(top.y - right.y),(top.x - right.x));
double dotv = ball.getSpeed().x*n.x + ball.getSpeed().y*n.y;
double dotn = n.x*n.x + n.y*n.y;
sf::Vector2f u = sf::Vector2f((dotv/dotn)*n.x, (dotv/dotn)*n.y);
sf::Vector2f w = ball.getSpeed() - u;
ball.setSpeed(sf::Vector2f(ball.getSpeed().x,ball.getSpeed().y) - w);
At first I made the mistake of calculating dotproducts as vectors this has been resolved, now it still gives me a strange output It fires my ball directly trough my object in the angle of the reversed normal
Any help would be greatly appreciated.
One problem I see is that you have dot products as vectors. A dot product results in a scalar (single value).
Also, to make your life a lot easier, you make functions for vector operations and even overload operators when appropriate. E.g. vector addition, subtraction. It's probably best to regular functions for dot product and cross product. Here are some examples of what I mean
class Vector2f
{
// Member of Vector2f
X& operator+=(const Vector2f& other)
{
x += other.x;
y += other.y;
return *this;
}
};
// Not member of Vector2f
inline Vector2f operator+(Vector2f a, const Vector2f& b)
{
a += b;
return a;
}
double dot(const Vector2f& a, const Vector2f& b)
{
return a.getX()*b.getX() + a.getY()*b.getY();
}

Check if mouse is within triangle C++

I'm making a application for school in which I have to click a particular object.
EDIT: This is being made in 2D
I have a rectangle, I rotate this rectangle by X.
The rotation of the rectangle has made my rectangles (x,y,width,height) become a new rectangle around the rotated rectangle.
http://i.stack.imgur.com/MejMA.png
(excuse me for my terrible paint skills)
The Black lines describe the rotated rectangle, the red lines are my new rectangle.
I need to find out if my mouse is within the black rectangle or not. Whatever rotation I do I already have a function for getting the (X,Y) for each corner of the black rectangle.
Now I'm trying to implement this Check if point is within triangle (The same side technique).
So I can either check if my mouse is within each triangle or if theres a way to check if my mouse is in the rotated rectangle that would be even better.
I practically understand everything written in the triangle document, but I simply don't have the math skills to calculate the cross product and the dot product of the 2 cross products.
This is supposed to be the cross product:
a × b = |a| |b| sin(θ) n
|a| is the magnitude (length) of vector a
|b| is the magnitude (length) of vector b
θ is the angle between a and b
n is the unit vector at right angles to both a and b
But how do I calculate the unit vector to both a and b?
And how do I get the magnitude of a vector?
EDIT:
I forgot to ask for the calculation of the dotproduct between 2 cross products.
function SameSide(p1,p2, a,b)
cp1 = CrossProduct(b-a, p1-a)
cp2 = CrossProduct(b-a, p2-a)
if DotProduct(cp1, cp2) >= 0 then return true
else return false
Thank you everyone for your help I think I got the hang of it now, I wish I could accept multiple answers.
If you are having to carry out loads of check, I would shy away from using square root functions: they are computationally expensive. for comparison purposes, just multiply everything by itself and you can bypass the square rooting:
magnitude of vector = length of vector
If vector is defined as float[3] length can be calculated as follows:
double magnitude = sqrt( a[0]*a[0] + a[1]*a[1] + a[2]*a[2] );
However that is expensive computationally so I would use
double magnitudeSquared = a[0]*a[0] + a[1]*a[1] + a[2]*a[2];
Then modify any comparative calculations to use the squared version of the distance or magnitude and it will be more performant.
For the cross product, please forgive me if this maths is shaky, it has been a couple of years since I wrote functions for this (code re-use is great but terrible for remembering things):
double c[3];
c[0] = ( a[1]*b[2] - a[2]*b[1] );
c[1] = ( a[2]*b[0] - a[0]*b[2] );
c[2] = ( a[0]*b[1] - a[1]*b[0] );
To simplify it all I would put a vec3d in a class of its own, with a very simple representation being:
class vec3d
{
public:
float x, y, z;
vec3d crossProduct(vec3d secondVector)
{
vec3d retval;
retval.x = (this.y * secondVector.z)-(secondVector.y * this.z);
retval.y = -(this.x * secondVector.z)+(secondVector.x * this.z);
retval.z = (this.x * secondVector.y)-(this.y * secondVector.x);
return retval;
}
// to get the unit vector divide by a vectors length...
void normalise() // this will make the vector into a 1 unit long variant of itself, or a unit vector
{
if(fabs(x) > 0.0001){
x= x / this.magnitude();
}
if(fabs(y) > 0.0001){
y= y / this.magnitude();
}
if(fabs(z) > 0.0001){
z = / this.magnitude();
}
}
double magnitude()
{
return sqrt((x*x) + (y*y) + (z*z));
}
double magnitudeSquared()
{
return ((x*x) + (y*y) + (z*z));
}
};
A fuller implementation of a vec3d class can be had from one of my old 2nd year coding excercises: .h file and .cpp file.
And here is a minimalist 2d implementation (doing this off the top of my head so forgive the terse code please, and let me know if there are errors):
vec2d.h
#ifndef VEC2D_H
#define VEC2D_H
#include <iostream>
using namespace std;
class Vec2D {
private:
double x, y;
public:
Vec2D(); // default, takes no args
Vec2D(double, double); // user can specify init values
void setX(double);
void setY(double);
double getX() const;
double getY() const;
double getMagnitude() const;
double getMagnitudeSquared() const;
double getMagnitude2() const;
Vec2D normalize() const;
double crossProduct(Vec2D secondVector);
Vec2D crossProduct(Vec2D secondVector);
friend Vec2D operator+(const Vec2D&, const Vec2D&);
friend ostream &operator<<(ostream&, const Vec2D&);
};
double dotProduct(const Vec2D, const Vec2D);
#endif
vec2d.cpp
#include <iostream>
#include <cmath>
using namespace std;
#include "Vec2D.h"
// Constructors
Vec2D::Vec2D() { x = y = 0.0; }
Vec2D::Vec2D(double a, double b) { x = a; y = b; }
// Mutators
void Vec2D::setX(double a) { x = a; }
void Vec2D::setY(double a) { y = a; }
// Accessors
double Vec2D::getX() const { return x; }
double Vec2D::getY() const { return y; }
double Vec2D::getMagnitude() const { return sqrt((x*x) + (y*y)); }
double Vec2D::getMagnitudeSquared() const { return ((x*x) + (y*y)); }
double Vec2D::getMagnitude2 const { return getMagnitudeSquared(); }
double Vec2d::crossProduct(Vec2D secondVector) { return ((this.x * secondVector.getY())-(this.y * secondVector.getX()));}
Vec2D crossProduct(Vec2D secondVector) {return new Vec2D(this.y,-(this.x));}
Vec2D Vec2D::normalize() const { return Vec2D(x/getMagnitude(), y/getMagnitude());}
Vec2D operator+(const Vec2D& a, const Vec2D& b) { return Vec2D(a.x + b.x, a.y + b.y);}
ostream& operator<<(ostream& output, const Vec2D& a) { output << "(" << a.x << ", " << a.y << ")" << endl; return output;}
double dotProduct(const Vec2D a, const Vec2D b) { return a.getX() * b.getX() + a.getY() * b.getY();}
Check if a point is inside a triangle described by three vectors:
float calculateSign(Vec2D v1, Vec2D v2, Vec2D v3)
{
return (v1.getX() - v3.getX()) * (v2.getY() - v3.getY()) - (v2.getX() - v3.getX()) * (v1.getY() - v3.getY());
}
bool isPointInsideTriangle(Vec2D point2d, Vec2D v1, Vec2D v2, Vec2D v3)
{
bool b1, b2, b3;
// the < 0.0f is arbitrary, could have just as easily been > (would have flipped the results but would compare the same)
b1 = calculateSign(point2d, v1, v2) < 0.0f;
b2 = calculateSign(point2d, v2, v3) < 0.0f;
b3 = calculateSign(point2d, v3, v1) < 0.0f;
return ((b1 == b2) && (b2 == b3));
}
In the code above if calculateSign is in the triangle you will get a true returned :)
Hope this helps, let me know if you need more info or a fuller vec3d or 2d class and I can post:)
Addendum
I have added in a small 2d-vector class, to show the differences in the 2d and 3d ones.
The magnitude of a vector is its length. In C++, if you have a vector represented as a double[3], you would calculate the length via
#include <math.h>
double a_length = sqrt( a[0]*a[0] + a[1]*a[1] + a[2]*a[2] );
However, I understand what you actually want is the cross product? In that case, you may want to calculate it directly. The result is a vector, i.e. c = a x b.
You code it like this for example:
double c[3];
c[0] = ( a[2]*b[3] - a[3]*b[2] );
c[1] = ( a[3]*b[1] - a[1]*b[3] );
c[2] = ( a[1]*b[2] - a[2]*b[1] );
You can calculate the magnitude of vector by sqrt(x*x + y*y). Also you can calculate the crossproduct simpler: a x b = a.x * b.y - a.y * b.x. Checking that a point is inside triangle can be done by counting the areas for all 4 triangles. For example a is the area of the source triangle, b,c,d are areas of other ones. If b + c + d = a then the point is inside. Counting the area of triangle is simple: we have vectors a, b that are vertexes of triangle. The area of triangle then is (a x b) / 2
One simple way without getting into vectors is to check for area.
For example ,lets say you have a rectangle with corners A,B,C,D. and point P.
first calculate the area of rectangle, simply find height and width of the rectangle and multiply.
B D
| /
| /
|/____ C
A
For calculating the height,width take one point lets say A, find its distance from all other three points i.e AB,AC,AD 1st and 2nd minimum will be width,and height, max will be diagonal length.
Now store the points from which you get the height, width, lets says those points are B,C.
So now you know how rectangle looks, i.e
B _____ D
| |
|_____|
A C
Then calculate the sum of area of triangles ACP,ABP,BDP,CDP (use heros formula to compute area of rectangle), if it equals to the area of rectangle, point P is inside else outside the rectangle.