Mathematical vectors

Haha, I believe I’m in the same pool as CyanPrime here :stuck_out_tongue:

Alright, alright, so I think I’ve got it understood now that I fiddled with it/added it (Vectors and Points) to my code, thus ending up with position as a Point and velocity being a Vector. Having changed position to being a Point instead of a Vector causes a problem though and I can’t seem to find out why. I think it has to do with setLocation(double x, double y) being converted to integers inside the Point class, but it causes a problem while I try to rotate the car. When position was a Vector I didn’t have this problem, even when type casting and rounding the x and y in my car class.

Here is a snippet of the current code.

This is part of my move function inside the car class.


velocity = new Vector2D(Math.sin(Math.toRadians(carAngle)) * (currentSpeed * deltaSeconds), -Math.cos(Math.toRadians(carAngle)) * (currentSpeed * deltaSeconds));
position = Vector2D.add(position, velocity);

This is the part of the Vector class.


public static Point add(Point p, Vector2D v) {
	Point newP = new Point();
	newP.setLocation(v.x + p.x, v.y + p.y);
	return newP;
}

and this is the part of the render function within my car class.


AffineTransform savedAT = g.getTransform();
AffineTransform newAT = AffineTransform.getRotateInstance(Math.toRadians(carAngle),	position.getX(), position.getY());
		
g.setTransform(newAT);
g.drawImage(carImage, (int) Math.round(position.getX()), (int)Math.round(position.getY()), null);
g.setTransform(savedAT);

I’m pretty sure the rotation is messed up because of the getX() and getY() functions of the Point class, or it can be the problem when I use setLocation from the Point class in my car constructor… as follows


public Car() {
	health = 100;
	score = 0;
	startX = 40.0;
	startY = 480.0;
	position = new Point();
	position.setLocation(startX, startY);	
}

Anyone got any thoughts as to why rotation is acting buggy?

I think you’ve found the solution to your problem all by yourself: use double for the position instead of int by using java.awt.geom.Point2D.Double instead of java.awt.Point.

Hahahaha, thanks! works like a charm now :D, didn’t know about Point2D :slight_smile:

;D

I also learned a lot from this thread too :stuck_out_tongue:

Nooo! Don’t do this! Vectors and points are abstract concepts, Vector2D and awt.Point are concrete things - they are very different! When I talked about ‘points’ and ‘vectors’ I was talking in the abstract, ie how to think about them. I wasn’t talking about how you should represent them in code. In most contexts always use Vector2D to store information whether it’s a ‘location’ or a ‘vector’. Only convert values to int when you absolutely have to.

So you are telling me I should basically keep Points inside the car class itself instead of mixing it up with Vector2D??? or should I use Vector2D to represent position and totally omit Point?

Jeez Simon, do you have to confuse us further ;D

Why would you use a Vector to represent a position?

Because it’s nice to understand the difference in how things work mathematically so you can work algebraically but (unless there’s a good reason) no need to implement them as individual classes (at least in OO). Or perhaps you do, but the class hierarchy is mathematically illogical simply because it’s a better fit from a coding perspective.

Yes.

I had a go at answering this a few posts back.

Ah yes found it ;D
So magnitude is sqrt(aa+bb) and direction is in degrees?

I must admit that you guys make for confusing reading. I haven’t read everything here so sorry if I missed something.

I think its important to note, that when we do real mathematics, things have a lot of context which can be useful in code. We often will represent a position in a coordinate space with a vector (lets call it R). We have a lot of context here (not always explicit and often generic). The coordinate system, the dimension, and most importantly that we are interpreting R as a position. In real code we may want to enforce that R is a position with type information so we only use it where it makes sense. ie have a class Position.

Of course in other cases we may just want a generic Vector class. Whats best depends on the use case.

We see this in math programs like R that allow all sorts of conversions from one type to another. You can’t do everything with a single “type” but you can pretty much convert most things. This makes the cast explicit and perhaps makes the coder think about if what one is doing makes sense.

For my code at least: I have seen my enemy, and he is me. So trying to enforce correct usage where I can is typically worth it.

Thanks delt0r, makes sense :smiley:

[quote=“deadly72,post:47,topic:36402”]
Yes - it keeps the code a lot cleaner and less error-prone. Simply use sensible variable naming to remind you what things are.
After all, it doesn’t really matter how the data is stored, what matters is that you understand what the data represents.
There are other advantages to doing things this way which I won’t go into here but which you’ll no doubt discover if you start to use vectors a lot!

Most commonly you’ll think about 2D vectors in rectangular form: (a,b), where this is explictly the “direction” and the magnitude (m) is as you’ve stated. Another way to think is in polar form: (m,t), where m is the magnitude and “t” in the angle is some measure, of which degrees is one possible choice.

I am a mechanical engineer(profession and bachelors). I learned a lot and also use vectors and a lot of 3d spatial things on a daily basis.

And this thread made my head hurt. So much confusion back and forth!

Unfortunately, wolfram and many other math and spatial sites often show the “complete” or “advanced” picture of things, where their examples are far more complex(albeit complete) than what is actually necessary to understand what you actually need it for.

I looked around on the internet a lot, and there is clearly a lot of examples and pictures that I feel are poorly drawn when describing vectors, that would definitely lead to confusion. I would highly recommend just keep at it! It will sink in!

Co-Pilot Roger Murdock(to Capt. Oveur): We have clearance, Clarence.
Capt. Oveur: Roger, Roger. What’s our vector, Victor?

[quote=“SimonH,post:54,topic:36402”]

Alright, so I’ve changed the Vector2D class and the car class to only use Vectors and not Points as mentioned, and it does keep the code much cleaner and less error prone.

So I’ve been trying to find out the direction in angles, as this is one of the main things that represents a vector! :P. My car is moving from the origin which is set through my car constructor Vector2D position = new Vector2D(40,480); and I believe I’ve hit a road block. The code is updated in my move method


...
velocity = new Vector2D(Math.sin(Math.toRadians(carAngle)) * (currentSpeed * deltaSeconds), -Math.cos(Math.toRadians(carAngle)) * (currentSpeed * deltaSeconds));
position = Vector2D.add(position, velocity);
...

My understanding of the following two statements it seems hasn’t sunk in.

To get the angle do I need to normalize the vector first? If so it should be pretty simple giving


public Vector2D normalize() {
	double dummyx, dummyy;
	dummyx = x;
	dummyy = y;
		
	dummyx /= getMagnitude();
	dummyy /= getMagnitude();
		
	return new Vector2D(dummyx, dummyy);
}

the part that gets me confused is the next to get the angle. This is what I have


public double getAngle() {
	return Math.atan2(y, x);
}

I’m pretty sure that is the problem with trying to find the angle because I’m getting bogus values. (and if normalization needs to occur first then it would be return Math.atan2(normalizedVector.y, normalizedVector.x)) ?

In addition to getting the angle, I’ve been trying to figure out how to reverse the direction of the vector (Which should be simple!). From what I’ve read it seems that to reverse the direction a simple scaling operation on the vector with negative 1 should do the trick. Something around these lines?


public void scale(int scaleFactor) {
	x *= scaleFactor;
	y *= scaleFactor;
}

I don’t get how that works because if you scale a vector with negative 1 you will just have the resulting negative coordinates. I think once these two problems are solved I will see a light at then end of the tunnel, but till then I can’t seem to figure out what is going on.

Oh, and a quick side note: I’ve seen so many people use floats instead of doubles for positioning. Whats the reasoning behind it and should I change the variables to represent floats instead?

To get the angle do I need to normalize the vector first? If so it should be pretty simple giving

no, but do you notice it is radian not degree ?

Oh, and a quick side note: I've seen so many people use floats instead of doubles for positioning.  Whats the reasoning behind it and should I change the variables to represent floats instead?

nowadays float is better suitable for hardware, but personnaly I prefer double as it give a lot higer resolution than float and enable NaN (matematical unresolvable) gesture

This was code ra4king gave you a bit ago and you’ve been using it since, but it has a bug in it.


...
velocity = new Vector2D(Math.sin(Math.toRadians(carAngle)) * (currentSpeed * deltaSeconds), -Math.cos(Math.toRadians(carAngle)) * (currentSpeed * deltaSeconds));
position = Vector2D.add(position, velocity);
...

If you’re creating an (a, b) vector from an angle (in this case, carAngle) and magnitude (in this case, currentSpeed * deltaSeconds) you want to have (a, b) = (magnitude * cos(angle), magnitude * sin(angle)) but right now you have them swapped and are using sin in your x coordinate’s equation, and cos in your y’s.

As DzzD hinted at, Math.atan2 and Math.atan return angle values in radians and not degrees. If you want degrees, just use Math.toDegrees(Math.atan2(y, x)).

Also, you do not need to normalize the vector before getting the angle. Math.atan and Math.atan2 both compute the arctan function, which in math takes a single scalar: arctan(y / x). If m is the magnitude of (x, y), then arctan( (y/m) / (x/m) ) = arctan( (y / x) * (1/m)/(1/m) ) = arctan(y / x)

Math.atan2 separates the arguments so you don’t accidentally divide by 0 and you can use the signs on y and x to determine which quadrant the angle should be in.

Oh good catch! Didn’t notice that silly error.
But, is that a negative I see before the Math.cos? Why?