Calculate next position and velocity after âbounceâ
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
1
down vote
favorite
Intro and code
I have the following function that calculates an objects "next" position and velocity (in 1 dimension) given a boundary [0, max]
.
public TwoVector<Double> getNextPositionAndVelocity(double position, double velocity, double max)
if (position + velocity < 0)
return TwoVector.<Double>builder()
.x(Math.abs(position + velocity))
.y(Math.abs(velocity))
.build();
if (position + velocity > max)
return TwoVector.<Double>builder()
.x(max - ((position + velocity) % max))
.y(-Math.abs(velocity))
.build();
return TwoVector.<Double>builder()
.x(position + velocity)
.y(velocity)
.build();
Explanation
- The first condition checks if adding the current velocity to the current position would cause the object to be beyond the "left" boundary. If that's the case, the next position should be equal to the amount the object would be beyond the left boundary added to the left boundary and the next velocity should point the object to the "right".
- The second condition checks if adding the current velocity to the current position would cause the object to beyond the "right" boundary. If that's the case, the next position should be equal to the amount the object would be beyond the boundary subtracted from the boundary and the next velocity should point the object to the "left".
- If neither condition is true, we can add the current velocity to the current position to get the next position without issue.
Question
Are there more straightforward functions to calculate each of these "next" values? Perhaps a function that "collapses" these branches?
java coordinate-system physics
add a comment |Â
up vote
1
down vote
favorite
Intro and code
I have the following function that calculates an objects "next" position and velocity (in 1 dimension) given a boundary [0, max]
.
public TwoVector<Double> getNextPositionAndVelocity(double position, double velocity, double max)
if (position + velocity < 0)
return TwoVector.<Double>builder()
.x(Math.abs(position + velocity))
.y(Math.abs(velocity))
.build();
if (position + velocity > max)
return TwoVector.<Double>builder()
.x(max - ((position + velocity) % max))
.y(-Math.abs(velocity))
.build();
return TwoVector.<Double>builder()
.x(position + velocity)
.y(velocity)
.build();
Explanation
- The first condition checks if adding the current velocity to the current position would cause the object to be beyond the "left" boundary. If that's the case, the next position should be equal to the amount the object would be beyond the left boundary added to the left boundary and the next velocity should point the object to the "right".
- The second condition checks if adding the current velocity to the current position would cause the object to beyond the "right" boundary. If that's the case, the next position should be equal to the amount the object would be beyond the boundary subtracted from the boundary and the next velocity should point the object to the "left".
- If neither condition is true, we can add the current velocity to the current position to get the next position without issue.
Question
Are there more straightforward functions to calculate each of these "next" values? Perhaps a function that "collapses" these branches?
java coordinate-system physics
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
Intro and code
I have the following function that calculates an objects "next" position and velocity (in 1 dimension) given a boundary [0, max]
.
public TwoVector<Double> getNextPositionAndVelocity(double position, double velocity, double max)
if (position + velocity < 0)
return TwoVector.<Double>builder()
.x(Math.abs(position + velocity))
.y(Math.abs(velocity))
.build();
if (position + velocity > max)
return TwoVector.<Double>builder()
.x(max - ((position + velocity) % max))
.y(-Math.abs(velocity))
.build();
return TwoVector.<Double>builder()
.x(position + velocity)
.y(velocity)
.build();
Explanation
- The first condition checks if adding the current velocity to the current position would cause the object to be beyond the "left" boundary. If that's the case, the next position should be equal to the amount the object would be beyond the left boundary added to the left boundary and the next velocity should point the object to the "right".
- The second condition checks if adding the current velocity to the current position would cause the object to beyond the "right" boundary. If that's the case, the next position should be equal to the amount the object would be beyond the boundary subtracted from the boundary and the next velocity should point the object to the "left".
- If neither condition is true, we can add the current velocity to the current position to get the next position without issue.
Question
Are there more straightforward functions to calculate each of these "next" values? Perhaps a function that "collapses" these branches?
java coordinate-system physics
Intro and code
I have the following function that calculates an objects "next" position and velocity (in 1 dimension) given a boundary [0, max]
.
public TwoVector<Double> getNextPositionAndVelocity(double position, double velocity, double max)
if (position + velocity < 0)
return TwoVector.<Double>builder()
.x(Math.abs(position + velocity))
.y(Math.abs(velocity))
.build();
if (position + velocity > max)
return TwoVector.<Double>builder()
.x(max - ((position + velocity) % max))
.y(-Math.abs(velocity))
.build();
return TwoVector.<Double>builder()
.x(position + velocity)
.y(velocity)
.build();
Explanation
- The first condition checks if adding the current velocity to the current position would cause the object to be beyond the "left" boundary. If that's the case, the next position should be equal to the amount the object would be beyond the left boundary added to the left boundary and the next velocity should point the object to the "right".
- The second condition checks if adding the current velocity to the current position would cause the object to beyond the "right" boundary. If that's the case, the next position should be equal to the amount the object would be beyond the boundary subtracted from the boundary and the next velocity should point the object to the "left".
- If neither condition is true, we can add the current velocity to the current position to get the next position without issue.
Question
Are there more straightforward functions to calculate each of these "next" values? Perhaps a function that "collapses" these branches?
java coordinate-system physics
edited Apr 28 at 21:37
200_success
123k14142399
123k14142399
asked Apr 28 at 20:58
geofflittle
825
825
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
0
down vote
I.
x(max - ((position + velocity) % max))
doesn't look quite right. % max
does not help here much (see below) it is better replaced with - max
, and thus the whole formula turns into 2 * max - (position + velocity)
.
II. Do you assume large velocities are impossible, in other words, in the first alternative, can you guarantee that Math.abs(position + velocity)
is always LE than max
?
add a comment |Â
up vote
0
down vote
I assume "next" in getNextPositionAndVelocity
means "after one unit of whatever temporal unit you use in the unit of the velocity", since the change of a position based on a velocity only makes sense in the context of a time span.
As for your code, you could simply model the path of the object by breaking it up into subpaths where the direction does not change, like this:
public double getNextPositionAndVelocity(double position, double velocity, double max)
double remainingDistance = Math.abs(velocity);
double currentVelocity = velocity;
double currentPosition = position;
while (remainingDistance > 0.0)
double nextBoundary;
if (currentVelocity < 0.0)
nextBoundary = 0.0;
else
assert currentVelocity > 0.0; //cannot be 0 or NaN, not if we're in the loop
nextBoundary = max;
double maximumDistanceToTravelInCurrentDirection = Math.abs(nextBoundary - currentPosition);
if (maximumDistanceToTravelInCurrentDirection <= remainingDistance)
currentPosition = nextBoundary;
remainingDistance -= maximumDistanceToTravelInCurrentDirection;
currentVelocity *= -1;
else
currentPosition += remainingDistance * Math.signum(currentVelocity);
remainingDistance = 0;
return new doublecurrentPosition, currentVelocity;
Admittedly, this is more code than your version, but then, you don't consider the possibility that the range is smaller than the velocity, and if this is the case, an object might bounce off an edge more than once.
The above code could be optimized by first calculating the velocity modulo twice the range, because after two range lenghts, the position and velocity of the object will be identical to its initial position and velocity.
Also, you should validate the arguments. This not only entails checking whether the arguments are valid with respect to each other (e.g. whether position
lies within the permitted range), but also handling special cases like the infinities or Double.NaN
. E.g., if you check whether position >= 0 && position <= max
, then you automatically have NaN
covered for position
and max
, because the comparison operators and the equality operator ==
always return false
if one operand is NaN
(even Double.NaN == Double.NaN
returns false
, which is why there's a method Double.isNaN(double)
), but position
might still be Double.POSITIVE_INFINITY
if max
is also Double.POSITIVE_INFINITY
. Also, max
should probably be greater than 0
(which would not be covered by the aforementioned condition either).
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
I.
x(max - ((position + velocity) % max))
doesn't look quite right. % max
does not help here much (see below) it is better replaced with - max
, and thus the whole formula turns into 2 * max - (position + velocity)
.
II. Do you assume large velocities are impossible, in other words, in the first alternative, can you guarantee that Math.abs(position + velocity)
is always LE than max
?
add a comment |Â
up vote
0
down vote
I.
x(max - ((position + velocity) % max))
doesn't look quite right. % max
does not help here much (see below) it is better replaced with - max
, and thus the whole formula turns into 2 * max - (position + velocity)
.
II. Do you assume large velocities are impossible, in other words, in the first alternative, can you guarantee that Math.abs(position + velocity)
is always LE than max
?
add a comment |Â
up vote
0
down vote
up vote
0
down vote
I.
x(max - ((position + velocity) % max))
doesn't look quite right. % max
does not help here much (see below) it is better replaced with - max
, and thus the whole formula turns into 2 * max - (position + velocity)
.
II. Do you assume large velocities are impossible, in other words, in the first alternative, can you guarantee that Math.abs(position + velocity)
is always LE than max
?
I.
x(max - ((position + velocity) % max))
doesn't look quite right. % max
does not help here much (see below) it is better replaced with - max
, and thus the whole formula turns into 2 * max - (position + velocity)
.
II. Do you assume large velocities are impossible, in other words, in the first alternative, can you guarantee that Math.abs(position + velocity)
is always LE than max
?
answered Apr 28 at 22:30
bipll
3926
3926
add a comment |Â
add a comment |Â
up vote
0
down vote
I assume "next" in getNextPositionAndVelocity
means "after one unit of whatever temporal unit you use in the unit of the velocity", since the change of a position based on a velocity only makes sense in the context of a time span.
As for your code, you could simply model the path of the object by breaking it up into subpaths where the direction does not change, like this:
public double getNextPositionAndVelocity(double position, double velocity, double max)
double remainingDistance = Math.abs(velocity);
double currentVelocity = velocity;
double currentPosition = position;
while (remainingDistance > 0.0)
double nextBoundary;
if (currentVelocity < 0.0)
nextBoundary = 0.0;
else
assert currentVelocity > 0.0; //cannot be 0 or NaN, not if we're in the loop
nextBoundary = max;
double maximumDistanceToTravelInCurrentDirection = Math.abs(nextBoundary - currentPosition);
if (maximumDistanceToTravelInCurrentDirection <= remainingDistance)
currentPosition = nextBoundary;
remainingDistance -= maximumDistanceToTravelInCurrentDirection;
currentVelocity *= -1;
else
currentPosition += remainingDistance * Math.signum(currentVelocity);
remainingDistance = 0;
return new doublecurrentPosition, currentVelocity;
Admittedly, this is more code than your version, but then, you don't consider the possibility that the range is smaller than the velocity, and if this is the case, an object might bounce off an edge more than once.
The above code could be optimized by first calculating the velocity modulo twice the range, because after two range lenghts, the position and velocity of the object will be identical to its initial position and velocity.
Also, you should validate the arguments. This not only entails checking whether the arguments are valid with respect to each other (e.g. whether position
lies within the permitted range), but also handling special cases like the infinities or Double.NaN
. E.g., if you check whether position >= 0 && position <= max
, then you automatically have NaN
covered for position
and max
, because the comparison operators and the equality operator ==
always return false
if one operand is NaN
(even Double.NaN == Double.NaN
returns false
, which is why there's a method Double.isNaN(double)
), but position
might still be Double.POSITIVE_INFINITY
if max
is also Double.POSITIVE_INFINITY
. Also, max
should probably be greater than 0
(which would not be covered by the aforementioned condition either).
add a comment |Â
up vote
0
down vote
I assume "next" in getNextPositionAndVelocity
means "after one unit of whatever temporal unit you use in the unit of the velocity", since the change of a position based on a velocity only makes sense in the context of a time span.
As for your code, you could simply model the path of the object by breaking it up into subpaths where the direction does not change, like this:
public double getNextPositionAndVelocity(double position, double velocity, double max)
double remainingDistance = Math.abs(velocity);
double currentVelocity = velocity;
double currentPosition = position;
while (remainingDistance > 0.0)
double nextBoundary;
if (currentVelocity < 0.0)
nextBoundary = 0.0;
else
assert currentVelocity > 0.0; //cannot be 0 or NaN, not if we're in the loop
nextBoundary = max;
double maximumDistanceToTravelInCurrentDirection = Math.abs(nextBoundary - currentPosition);
if (maximumDistanceToTravelInCurrentDirection <= remainingDistance)
currentPosition = nextBoundary;
remainingDistance -= maximumDistanceToTravelInCurrentDirection;
currentVelocity *= -1;
else
currentPosition += remainingDistance * Math.signum(currentVelocity);
remainingDistance = 0;
return new doublecurrentPosition, currentVelocity;
Admittedly, this is more code than your version, but then, you don't consider the possibility that the range is smaller than the velocity, and if this is the case, an object might bounce off an edge more than once.
The above code could be optimized by first calculating the velocity modulo twice the range, because after two range lenghts, the position and velocity of the object will be identical to its initial position and velocity.
Also, you should validate the arguments. This not only entails checking whether the arguments are valid with respect to each other (e.g. whether position
lies within the permitted range), but also handling special cases like the infinities or Double.NaN
. E.g., if you check whether position >= 0 && position <= max
, then you automatically have NaN
covered for position
and max
, because the comparison operators and the equality operator ==
always return false
if one operand is NaN
(even Double.NaN == Double.NaN
returns false
, which is why there's a method Double.isNaN(double)
), but position
might still be Double.POSITIVE_INFINITY
if max
is also Double.POSITIVE_INFINITY
. Also, max
should probably be greater than 0
(which would not be covered by the aforementioned condition either).
add a comment |Â
up vote
0
down vote
up vote
0
down vote
I assume "next" in getNextPositionAndVelocity
means "after one unit of whatever temporal unit you use in the unit of the velocity", since the change of a position based on a velocity only makes sense in the context of a time span.
As for your code, you could simply model the path of the object by breaking it up into subpaths where the direction does not change, like this:
public double getNextPositionAndVelocity(double position, double velocity, double max)
double remainingDistance = Math.abs(velocity);
double currentVelocity = velocity;
double currentPosition = position;
while (remainingDistance > 0.0)
double nextBoundary;
if (currentVelocity < 0.0)
nextBoundary = 0.0;
else
assert currentVelocity > 0.0; //cannot be 0 or NaN, not if we're in the loop
nextBoundary = max;
double maximumDistanceToTravelInCurrentDirection = Math.abs(nextBoundary - currentPosition);
if (maximumDistanceToTravelInCurrentDirection <= remainingDistance)
currentPosition = nextBoundary;
remainingDistance -= maximumDistanceToTravelInCurrentDirection;
currentVelocity *= -1;
else
currentPosition += remainingDistance * Math.signum(currentVelocity);
remainingDistance = 0;
return new doublecurrentPosition, currentVelocity;
Admittedly, this is more code than your version, but then, you don't consider the possibility that the range is smaller than the velocity, and if this is the case, an object might bounce off an edge more than once.
The above code could be optimized by first calculating the velocity modulo twice the range, because after two range lenghts, the position and velocity of the object will be identical to its initial position and velocity.
Also, you should validate the arguments. This not only entails checking whether the arguments are valid with respect to each other (e.g. whether position
lies within the permitted range), but also handling special cases like the infinities or Double.NaN
. E.g., if you check whether position >= 0 && position <= max
, then you automatically have NaN
covered for position
and max
, because the comparison operators and the equality operator ==
always return false
if one operand is NaN
(even Double.NaN == Double.NaN
returns false
, which is why there's a method Double.isNaN(double)
), but position
might still be Double.POSITIVE_INFINITY
if max
is also Double.POSITIVE_INFINITY
. Also, max
should probably be greater than 0
(which would not be covered by the aforementioned condition either).
I assume "next" in getNextPositionAndVelocity
means "after one unit of whatever temporal unit you use in the unit of the velocity", since the change of a position based on a velocity only makes sense in the context of a time span.
As for your code, you could simply model the path of the object by breaking it up into subpaths where the direction does not change, like this:
public double getNextPositionAndVelocity(double position, double velocity, double max)
double remainingDistance = Math.abs(velocity);
double currentVelocity = velocity;
double currentPosition = position;
while (remainingDistance > 0.0)
double nextBoundary;
if (currentVelocity < 0.0)
nextBoundary = 0.0;
else
assert currentVelocity > 0.0; //cannot be 0 or NaN, not if we're in the loop
nextBoundary = max;
double maximumDistanceToTravelInCurrentDirection = Math.abs(nextBoundary - currentPosition);
if (maximumDistanceToTravelInCurrentDirection <= remainingDistance)
currentPosition = nextBoundary;
remainingDistance -= maximumDistanceToTravelInCurrentDirection;
currentVelocity *= -1;
else
currentPosition += remainingDistance * Math.signum(currentVelocity);
remainingDistance = 0;
return new doublecurrentPosition, currentVelocity;
Admittedly, this is more code than your version, but then, you don't consider the possibility that the range is smaller than the velocity, and if this is the case, an object might bounce off an edge more than once.
The above code could be optimized by first calculating the velocity modulo twice the range, because after two range lenghts, the position and velocity of the object will be identical to its initial position and velocity.
Also, you should validate the arguments. This not only entails checking whether the arguments are valid with respect to each other (e.g. whether position
lies within the permitted range), but also handling special cases like the infinities or Double.NaN
. E.g., if you check whether position >= 0 && position <= max
, then you automatically have NaN
covered for position
and max
, because the comparison operators and the equality operator ==
always return false
if one operand is NaN
(even Double.NaN == Double.NaN
returns false
, which is why there's a method Double.isNaN(double)
), but position
might still be Double.POSITIVE_INFINITY
if max
is also Double.POSITIVE_INFINITY
. Also, max
should probably be greater than 0
(which would not be covered by the aforementioned condition either).
answered Apr 28 at 23:13
Stingy
1,888212
1,888212
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f193165%2fcalculate-next-position-and-velocity-after-bounce%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password