How do I calculate opposite of a vector, add some slack - c#

How can i calulate a valid range (RED) for my object's (BLACK) traveling direction (GREEN). The green is a Vector2 where x and y range is -1 to 1.
What I'm trying to do here is to create rocket fuel burn effekt. So what i got is
rocket speed (float)
rocket direction (Vector2 x = [-1, 1], y = [-1, 1])
I may think that rocket speed does not matter as fuel burn effect (particle) is created on position with its own speed.

A cheap and cheerful trick with 2D vectors is to transpose the x and y, then flip the sign on one of them to get the perpendicular vector (pseudo code):
Vector2 perpendicular ( -original.y, original.x ) // Or original.y, -original.x
Then you could do something like:
direction + perpendicular * rand(-0.3 , 0.3)
Update: having realised the question asks for the opposite vector (too busy looking at the picture!) I figure I had better answer that too. Multiply 'direction' by -1 to get the opposite vector. So this:
perpendicular * rand(-0.3 , 0.3) - direction
should give you a random direction vector somewhere in your range (not normalised, but close enough for these purposes). Then you can multiply that result by a random number depending on how long you want the tail.

If to expend upon OlduwanSteve's answer, you can make is such that it's somewhat physically accurate.
You want to create several vectors that will represent the expulsion (the red lines).
First define the number of vectors you want to represent the expulsion with - lets mark it n.
You want to get a set of n numbers which sum up to Vx. These numbers will be the x components of the expulsion vectors. You can do this like so (semi-pseudo code):
SumX = Vx;
for (i = 0; i < n; i++)
{
Ax[i] = -rand(0..SumX); // Ax is the array of all expulsion vectors x components
SumX -= Ax[i];
}
Now you'll want to calculate Ay (the y components of the expulsion vectors). This is quite similar to calculating the, except that SumY = 0.
Here instead of splitting up SumY among n elements, you need to decide a maximal y component. Best way I can think of to select this is to define a maximal allowed angle for the expulsion vectors and define the maximal Vy using: maxVy = minVx*tan(maxAlpha).
Now you can get Ay using this (semi-pseudo code):
SumY = maxVy*2; // The actual range is (-maxVy, maxVy), but using (0, 2*maxVy) is simpler IMO
for (i = 0; i < n; i++)
{
Ay[i] = rand(0..SumY);
SumY -= Ay[i];
}
for (i = 0; i < n; i++)
{
Ay[i] -= maxVy; // Translate the range back to (-maxVy, maxVy) from (0, 2*maxVy)
}
Now you have arrays of both the x and y components of the expulsion vectors. Iterate over both arrays and pair up elements to create the vectors (you don't have to iterate both arrays in the same order).
Notes:
• I align the axes in my calculations such that X is parallel to the objects speed vector (the green line).
• The calculation for maxVy does NOT guarantee that a vector of angle maxAlpha will be produced, it only guarantees that no vector of larger angle will be.
• The lines Ay[i] = rand(0..SumY) and Ax[i] = -rand(0..SumX) may lead to vectors with components of size 0. This may lead to annoying scenarios, I'd recommend to handle away such cases (for instance "while rand returns zero, call it again").

Related

How to find closest point on multisegment line

I'm trying to find a solution for best performance.
I need to find closet point on multisegment line (List points) to given point.
My line have thousands of points and I need to check distance to this line few times per second. So solution need to be very fast.
Right now I have something like below. It works but it is going to be slow when line have 10000+ points.
Maybe someone have idea how to make it faster?
public static float GetSqrDistXZ(Vector3 a, Vector3 b)
{
Vector3 vector = new Vector3(a.x - b.x, 0, a.z - b.z);
return vector.sqrMagnitude;
}
public static Vector3 NearestPointOnFiniteLine(Vector3 start, Vector3 end, Vector3 pnt)
{
Vector3 line = (end - start);
float len = Mathf.Sqrt(line.sqrMagnitude);
line.Normalize();
Vector3 v = pnt - start;
float d = (v.x * line.x) + (v.z * line.z);
d = Mathf.Clamp(d, 0f, len);
return start + line * d;
}
int pointsCount = line.points3.Count - 1; // line - List<Vector3> points.
float[] distances = new float[pointsCount];
for (int i = 0; i < pointsCount+1; i++) {
if (i >= 1) {
distances [i - 1] = GetSqrDistXZ (point, NearestPointOnFiniteLine (line.points3 [i - 1], line.points3 [i], point));
}
}
int minListIndexLeft = System.Array.IndexOf (distances, Mathf.Min (distances));
float minimalDistance = distances[minListIndexLeft];
Vector3 closestPoint = NearestPointOnFiniteLine (line.points3[minListIndexLeft], line.points3[minListIndexLeft+1], point);
You'll want to think about space partitioning. In this example I'm going to assume a 2D space, but this works in 3D just as well. Also there are much better solutions like BSP trees and stuff, but we'll keep it simple here.
Imagine putting a grid over your 2D space. Every segment (distance between 2 points) of your line intersects with one or more cells of that grid. What you have to do is to store the intersecting segments for every cell. If your line does not change, you can do that in one single pass on startup, or even store that information statically in an Asset.
But once you have that information, all you have to do is calculate the cell that your point is inside and then only check the line segments that intersect with that specific cell or a number of direct neighbours (see below). This makes finding the closest point lightning fast in comparison.
If you play with this idea on a piece of paper you may come across cases where this solution does not yield the closest point, because it did not consider a neighboring cell that contained a closer point. The easiest way to solve this is the following approach:
1. Find cell C, which is the cell your point is in
2. Let cellRange = 0
3. Let point B be undefined
4. Find closest point P among all segments that intersect cell C and its neighboring cells of range cellRange*
5. If B is the same as newly found point P then P is the solution. You are done.
6. Increase cellRange by 1
7. Let B = P
8. Repeat from step 4
* "neighboring cells of range cellRange" means:
cellRange 0: only cell C, no neighbours
cellRange 1: cell C and direct neighbours
cellRange 2: cell C, direct neighbours and their direct neighbours
...
This solution basically checks if increasing the search range improves the solution. As soon as increasing the range did not improve the solution, you found the closest point.

I have a list of points and would like to determine if they form a circle

I'm using C#, I have a list of Vector points and would like to try and approximate how close they look like a circle.
Any ideas how to implement this or if someone else has?
Based on the "gestures" tag I guess you not only want to know how close are these points to the smallest-circle (search for "Smallest-circle problem"), but you have to be concerned also about their order and spread:
I would start with the distance from the smallest-circle. If they are too far, you're done, it's not a circle.
If they are close enough to your configured threshold, compute the angle between the vector defined by the circle center, first point and each other point (picture bellow)
Check that each angle is greater than the previous.
Check that difference between any two angles next to each other is not over some configured threshold.
Check that the last point is close enough to the first one.
You will probably think of some other checks eventually, so make it simple to extend.
Another possibility:
Find the centroid
(http://en.wikipedia.org/wiki/Centroid#Of_a_finite_set_of_points) of
the points
Determine the distance (radius) of each point from the location of
the centroid
Calculate the distribution and determine if the points
are within acceptable tolerances (e.g. standard deviation < ±0.05 × mean radius or something like that)
Without knowing more about the source of the points, it's hard to suggest the best solution.
These might be of use: http://link.springer.com/article/10.1007%2FBF02276879#page-1 and http://www.dtcenter.org/met/users/docs/write_ups/circle_fit.pdf. Those methods will give you the best fitting circle through the points, but you are still going to need to determine whether your data points are close enough for your purposes.
UPDATE: based on the 'gesture' tag, somebody has already implemented it: http://depts.washington.edu/aimgroup/proj/dollar/
1) Pick any three points from that list, find the center of their appropriate circle
We can do this, using triangle circumcircle construction method, you find the medians of all three sides (two are sufficient) and their intersection is the center of the circle. Something like this:
public PointF findCenter(PointF a, PointF b, PointF c)
{
float k1 = (a.Y - b.Y) / (a.X - b.X) //Two-point slope equation
float k2 = (a.Y - c.Y) / (a.X - c.X) //Same for the (A,C) pair
PointF midAB = new PointF((a.X + b.X) / 2, (a.Y + b.Y) / 2) //Midpoint formula
PointF midAC = new PointF((a.X + c.X) / 2, (a.Y + c.Y) / 2) //Same for the (A,C) pair
k1 = -1*k1; //If two lines are perpendicular, then the product of their slopes is -1.
k2 = -1*k2; //Same for the other slope
float n1 = midAB.Y - k1*midAB.X; //Determining the n element
float n2 = midAC.Y - k2*midAC.Y; //Same for (A,C) pair
//Solve y1=y2 for y1=k1*x1 + n1 and y2=k2*x2 + n2
float x = (n2-n1) / (k1-k2);
float y = k1*x + n1;
return new PointF(x,y);
}
2) Check if the other points are equivalently distanced from this center, if yes, you have a circle, if no, you don't.
P.S. I haven't tested the code, so be prepared to debug. Ask if you need anything else
Take any three points from your point set.
If the points are co-linear then, your point set doesn't all lie on a circle.
Find the circumcircle of the triangle. The diameter is given by: d = (a*b*c)/2*area. The center of the circle is the point of intersection of the perpendicular bisectors of the three sides.
Now for every remaining point in the point set, if the distance from the center is not equal to the radius then the points are not on a circle. You can speed up the calculations by comparing the square of the radius against the square of the distance between the given point and the center.

Randomly pick two numbers in a range so that the sum of their squares is constant

I'm currently developing a 2-player Ping-Pong game (in 2D - real simple) from scratch, and it's going good. However Theres a problem I just can't seem to solve - I'm not sure if this should be located here or on MathExchange - anyway here goes.
Initially the ball should be located in the center of the canvas. When pressing a button the ball should be fired off in a completely random direction - but always with the same velocity.
The Ball object has (simplified) 4 fields - The position in X and Y, and the velocity in X and Y. This makes it simple to bounce the ball off the walls when it hits, simple by inverting the velocities.
public void Move()
{
if (X - Radius < 0 || X + Radius > GameWidth)
{
XVelocity = -XVelocity;
}
if (Y - Radius < 0 || Y + Radius > GameHeight)
{
YVelocity = -YVelocity;
}
X+= XVelocity;
Y+= YVelocity;
}
I figured the velocity should be the same in each game, so I figures I would use Pythagoras - the square of the two velocities should always be the same.
SO for the question:
Is there a way to randomly select two numbers (doubles) such that the sum of their squares is always a specific number - more formally:
double x = RandomDouble();
double y = RandomDouble();
if (x^2 + y^2 = 16) {/* should always be true */ }
Any help appreciated :)
Randomly pick an angle theta and multiply that by the magnitude of the distance d you want. Something like:
double theta = rand.NextDouble() * 2.0 * Math.PI;
double x = d * Math.Cos(theta);
double y = d * Math.Sin(theta);
If the constant is C, pick a number x between 0 and sqrt(C).
Solve for the other number y using simple algebra.
why not try this:
double x = RandomDouble();
double y = square(16-x^2);
as your application allow double type.
does this solve your problem?
if not, please let me know

2d game vector movement C# [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I'm new in game development and I'm stuck in a problem.
I would like to know the new player position each seconds, here an example :
The player start at (2.5;2.5) and he go to (6.5;3.8).
His velocity is by example 2 units per seconds, and I would like to know the player position after 1sec. So something like this :
What I would like to know it's A every seconds but I don't know at all how I can do that...
I hope you will be able to help me, thanks in advance !
His velocity is by example 2 units per seconds.
I assume, that 'unit' means 'vector of length = 1'.
First of all, you need to calculate the AB vector (movement vector):
mov_vec = [xb-xa, yb-ya] = [6.5 - 2.5, 3.8 - 2.5] = [4, 1.3]
So, we know, that total unit did movement by [4, 1.3]. We need to normalize this vector. Normalized vector (unit vector) 'norm_mov_vec' will be codirectional with 'mov_vec', but it's length will be 1. See this link if you want to know more abut unit vectors.
Compute the length of movement vector:
mov_vec_len = sqrt( 4^2 + 1.3^2 ) ~= 4.2059
Compute normalized vector:
norm_mov_vec = [4/4.2059, 1.3/4.2059] ~= [0.9510, 0.3090]
And that's it. 'norm_mov_vec' is your 'unit-movement-vector', so if player is moving in that direction with speed of N units per second, you can very easily compute it's position after T seconds:
pos_after_T_sec_with_speed_N_units_per_sec = start_pos + ( N * T * norm_mov_vec )
EDIT:
Sample code, using Vector2 type from XNA. Can't test it, but I hope you will get the idea:
//In your case:
//start_pos = 'A' point
//end_pos = 'B' point
//time = number of seconds that elapsed
//speed = number of units per second
Vector2 calculatePosition(ref Vector2 start_pos, ref Vector2 end_pos, Uint32 time, Uint32 speed)
{
Vector2 mov_vec = Vector2.Substract(end_pos, start_pos);
Vector2 norm_mov_vec = Vector2.Normalize(mov_vec);
Vector2 delta_vec = norm_mov_vec * time * speed;
return Vector2.Add(start_pos, delta_vec);
}
First you need to work out the total distance covered, that's your vector. A vector is a movement, not two points in space.
Then you just divide each dimension, x and y in this case, by the time taken to do the move in unit of measurement (seconds) to get the distance per second.
Then you multiply each x and y by the number of seconds from 0, i.e. 1 second in your example, to get the position after 1 second.
I don't know what's available to you in your framework or libraries but a good Vector class will be so helpful, you'll want to be able to do math on the vector instance directly, such as:
Point origin = sprite.Position; // Assumes some sprite object with a position.
Point dest = new Point(200,344); // Destination.
Vector totalTranslation = new Vector(dest.X - origin.X, dest.Y - origin.Y);
Vector perSecond = totalTranslation / 60; // assuming takes a minute to move.
Vector distanceMoved = perSecond * 4; // distance moved after 4 seconds.
Point newPosition = new Point(origin.X + distanceMoved.X, origin.Y + distanceMoved.Y);
sprite.Position = newPosition; // Or using some orchestration class...
spriteManager.Move(sprite, newPosition); // ...like this.
Note being able to divide a vector directly. Else you have to divide each spatial dimension of the vector and make a new vector, or make a helper class to do it.
In real life, you might want to calculate based on milliseconds. I wouldn't use a fixed frame counter since it could look juddery, but work everything out based on a timer.
As I say, a good library or immutable Vector struct/class is the key here. Then its a case of thinking about the problem on graph paper.
Also, build up a palette of small functions you can chain together to do cooler, bigger stuff.
Another interesting problem is using an easing function to work out a coordinate after a given time to achieve the effect of a sprite slowing down as it 'lands'.
This is not programming, but vector math mostly, but anyway:
Your player is moving along the vector BA ( Point B minus Point A ) which is
Direction Vector: ( 4.0 / 1.3 )
This vector has a length of:
SquareRoot(4.0 * 4.0 + 1.3 * 1.3) = 4.2
A vector of the same direction and length of one unit would therefore be the vector with both components divided by the length of 4.2:
Direction Vector of length 1: (0.95 / 0.30)
As your player is fast and moves two units, it would be double length:
Direction Vector of length 2: (1.90 / 0.60)
Now each tick, add 1.90 and 0.60 respectively to your player coordinates, until they equal (roughly) the target coordinates.
x-displacement: 6.5-2.5 = 4
y-displacement: 3.8-2.5 = 1.3
Math.sqrt((4n)(4n)+(1.3n)(1.3n)) = 2
n=2/Math.sqrt(17.69)
x-displacement/second = 4n = 8/Math.sqrt(17.69) = 1.90207
y-displacement/second = 1.3n = 2.6/Math.sqrt(17.69) = 0.61817
so after get these values, it is really easy to calculate the position each second
You can use (as a general solution) these simple trigonometry formulae:
x = A.x + v * cos(fi) * t;
y = B.y + v * sin(fi) * t;
fi = atan2(B.y - A.y, B.x - A.x);
sample solution
// Since there's no common 2d Point double based type,
// let (x, y) point be represented as Tuple<Double, Double>
// where Item1 is x, and Item2 is y
public static Tuple<Double, Double> Move(Tuple<Double, Double> fromPoint,
Tuple<Double, Double> toPoint,
Double velocity,
Double time) {
Double fi = Math.Atan2(toPoint.Item2 - fromPoint.Item2, toPoint.Item1 - fromPoint.Item1);
return new Tuple<Double, Double>(
fromPoint.Item1 + velocity * Math.Cos(fi) * time,
fromPoint.Item2 + velocity * Math.Sin(fi) * time);
}
...
for (int t = 0; t < 10; ++t) {
Tuple<Double, Double> position =
Move(new Tuple<Double, Double>(2.5, 2.5),
new Tuple<Double, Double>(6.5, 3.8),
2.0,
t);
Console.Write("t = ");
Console.Write(t);
Console.Write(" x = ");
Console.Write(position.Item1);
Console.Write(" y = ");
Console.Write(position.Item2);
Console.WriteLine();
}

Randomly Generate Orthogonal 3x3 Matrix

I'm looking to do some complex part analysis within Seimens NX. I'm looking to implement the double caliper method of measuring a model in order to find the minimum possible box that it could possibly fit into(for machining purposes). I've got all of my measurement code in place, but I am completely baffled by the idea of a construct that can randomly output normalized 3x3 vectors for use as coordinate systems. The part is measured with respect to this coordinate system, so each coordinate system gives a unique "minimum part envelope". Once analyzed, the smallest envelope is selected and displayed.
this is the type of vector I am talking about:
1 0 0
0 1 0
0 0 1
numbers can be any value between -1 and 1, with decimals not only being accepted but pretty much required.
and no, this isn't my homework. More of an individual pursuit in my free time at work.
If you apply a rotation matrix to an already orthogonal matrix, then the result should also be orthogonal.
So you can redefine your problem as applying a random rotation matrix to the identity matrix.
Perhaps do one random rotation matrix for each axis (x,y,z) and then apply the matrices themselves in a random order?
If you don't mind to consider only a special subset of the orthogonal matrices, there is an easier way to achieve this, which is to take advantage of the Rodrigues' rotation formula to generate rotation matrices (which has an additional constraint that its determinant is equal to 1).
With this, you only need to generate a random 3x1 unit vector (as the rotation axis) and specify a rotation angle. This formula will transform them into a valid rotation matrix.
MATLAB example:
function R = rot(w, theta)
bw = [0, -w(3), w(2); w(3), 0, -w(1); -w(2), w(1), 0];
R = eye(3) + sin(theta)*bw + (1-cos(theta))*bw*bw;
end
w = rand(3,1)
w = w/norm(w)
R = rot(w, 3.14)
C++ example:
// w: the unit vector indicating the rotation axis
// theta: the rotation angle in radian
Eigen::Matrix3d MatrixExp3 (Eigen::Vector3d w, float theta){
Eigen::Matrix3d bw, R;
bw << 0, -w(2), w(1), w(2), 0, -w(0), -w(1), w(0), 0;
R << Eigen::Matrix3d::Identity() + std::sin(theta)*bw + (1-std::cos(theta))*bw*bw;
return R;
}
int main() {
std::srand((unsigned int) time(0));
Eigen::Vector3d w = Eigen::Vector3d::Random();
Eigen::Matrix3d R = MatrixExp3(w.normalized(), 3.14f);
std::cout << R << std::endl;
}

Categories