Mathematical issue (Increasing and deceasing two variables inside one loop) - java

I have a for loop and inside that integer x will increase from 533 to 813. That means 280 increments. In side the same loop I want to decrease y's value from 300 to 200 when above happens. Which means when x is 533 y must be 300 and when x is 813 y must be 200. I know this can do by decrease y's value by 100/280 in each iteration. But both are integers.
Here are some code sample i used but it is not working.:
for(int i = 0; i < b.getSize(); i++) {
x = b.getCar(i).getPosX();
b.getCar(i).setPosX(++x);
if(x >= ((getWidth() / 2) - 140) && x < ((getWidth() / 2) + 140)){
y = b.getCar(i).getPosY();
y = (double)(y - (10.0f / 28.0f));
b.getCar(i).setPosY((int)y);
}
}
How can I possibly do this. Thanks!

There are two solutions, a simple and a complex one. The simple one:
y = yoff + (int)( (double) height * x / width )
where yoff = 300, height = -100, width = 813-533. Basically, you do a floating point operation and then you round the result.
Alternatively, the same can be done using pure integer math using the Bresenham line algorithm but that would take a lot more code.

y must be a double or a float and you need to round its value when you want to use it.
If you wanna do animation, just have a look at interpolators. You can abstract the logic of computing the values in between your extremas.
Basically at the beginning, you give your interpolator the start and end values.
Then, you give the interpolator a time and it gives you back the value between start and end for that time value.
Bonus: it will allow you to change your animation look & feel without touching the rest of the code. (what you are trying to do is in fact a linear interpolation, but it will look much nicer using a sine function for instance, or some other algorithm such as bouncing, quadratic, ...)

It looks like the logic for drawing a line. The Bresenham's algorithm should be the best option.

Keep a helping variable double dy that keeps track of the precise value for y. At each iteration, update dy using your formula, then update y by taking the rounded/truncated value of dy.

NOt sure what you like to do, but your current solution sufers from rounding of floats to integers. To avoid this, calculate with floats / doubles and convert them to integer whensetting positions.

Related

DMX-values using sine and cosine. From 8bit (1 channel) to 16bit (two channels)

The bounty expires in 5 days. Answers to this question are eligible for a +50 reputation bounty.
droid is looking for a more detailed answer to this question.
I’m (still) working on a small project controlling DMX-lights (using Art-Net).
At the moment I’m working on the “Movement-generator” and what I basically do is to use sine and cosine to calculate the DMX values (0-255) for the pan- and tilt-channel, like with this method:
public void runSineMovement() {
double degrees = x;
double radians = Math.toRadians(degrees);
double sine = Math.sin(radians);
double dmxValue = (int) ((sine * 127) + 127);
dmxValuesOBJ.setDmxValuesInArray(1, (int) dmxValue);
SendArtnet.SendArtnetNow();
x = x + 1;
if (x > 360) {
x = 1;
}
}
x = 1
I then have a ScheduledExecutorService that will call that method on a regular interval, like this:
int speed = 100;
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleAtFixedRate(SineMovement::runSineMovement, 0, 100000 * speed, TimeUnit.NANOSECONDS);
Above is working just fine, moving head (tilt-channel in this example) is moving perfectly. Now I want to use the “fine-channel”, that is, go from 8bit to 16bit (from 1 channel to 2 channels controlling the tilt-channel) so I can get smooth movement even at very slow speed. Remember, "fine-channel" have to go from 0 to 255 first and then "coarse-channel" can go to 1, then "fine-channel" from 0 to 255 and then "coarse-channel" to 2, and so on.
Earlier I build a movement-generator with “triangle-effect” where I looped from 0 to 65.536 and back to 0 and so on, and on every run I calculated the “coarse-channel” (counter/256) and the “fine-channel” (counter % 256) and that approach is working just fine.
Any ideas on how to approach this when using sine and cosine when generating the effect? Can I use the approach from the triangle-generator calculating “coarse” and “fine” using division and modulus?
EDIT: When thinking about it, I don't think the "fine" should have the form as a sine-wave, I mean, the "fine" will (if using sine) go very, very, fast, both up and down, and that will mess things up if the "coarse" is still going "up". I guess the correct is that the "fine" will always have the sawtooth-shape -> sawtooth from zero to max when coarse is going up, and sawtooth from max to zero when coarse is going down. Does that makes sense?
Thanks 😊

How would I change an equation to modulate a number on a line, to one that that modulates on a sine curve?

I'm trying to modulate an alpha value in a Java application I'm building on Android. Right now it goes like this:
if (goingUp) {
newAlpha = oldAlpha + rateOfChange;
if (newAlpha > maxAlpha) {
newAlpha = maxAlpha;
goingUp = false;
}
} else {
newAlpha = oldAlpha - rateOfChange;
if (newAlpha < minAlpha) {
newAlpha = minAlpha;
goingUp = true;
}
}
Where rateOfChange is an arbitrary int that cannot be greater than maxAlpha. The equation is evaluate every tick in a thread and is independent of time.
Is there a way using only the variables given + Math.PI and other Math elements (I'm assuming Math.Sine will be in there) to get newAlpha to be a number on a Sine?
I'm thinking min and max would be the amp of the wave and rateOfChange would be a product of the Sine function, I just can't figure out how it all goes together.
Your equation will look like this:
y is vertical position at time t, A is the amplitude, f is the frequency, and t is the time (or ticks of your Android clock).
Why don't you consider this?
...at the top of your class definition, include:-
import java.lang.*;
...and within your function, after the assignment to newAlpha,
newAlpha = Math.sin(newAlpha%(2*Math.PI));
if you would like newAlpha to be in the range [-1,1] as the sin() function is
OR
...within your function, after the assignment to newAlpha,
newAlpha = Math.asin(newAlpha%3 - 1);
if you would like newAlpha to be in the range [-1,1] as the sin() function is
I'm not sure what datatype your newAlpha is, but I'm going to assume it will not affect the answer for this expression - like newAlpha is of type double.
It is generally the way to get a number within a certain range that you apply modulus to whatever expression you have ie. expr%N results in a number in range [0,N-1].
Hope this helps.
Based on duffymo's general equation I had to go all the way back to my TI-83 days (literally, put the app on my phone). But I was able to put all the pieces together so it ended up looking like this:
newAlpha = (int)((alphaMax - alphaMin) * 0.5 * Math.sin(rateOfChange * ticks + randomPhaseOffset) + (alphaMin + (alphaMax - alphaMin) * 0.5))
FMI: http://en.wikipedia.org/wiki/Sine_wave

Implement Generic Power Function Without Using Math.pow in Java

I want to write a program in java, which will perform a number raised to a power, but without using math.pow. The program should be generic to include fractions as well.
The loop increment method will increment by 1, which is okay for integers; but not fractions. Please Suggest a generic method that would be helpful to me.
First, observe that pow(a,x) = exp(x * log(a)).
You can implement your own exp() function using the Taylor series expansion for
ex:
ex = 1 + x + x2/2! + x3/3! + x4/4! + x5/5! + ...
This will work for non-integer values of x. The more terms you include, the more
accurate the result will be.
Note that by using some algebraic identities, you only need to resort to the series expansion for x in the range 0 < x < 1 . exp(int + frac) = exp(int)*exp(frac), and there's no need to use a series expansion for exp(int). (You just multiply it out,
since it's an integer power of e=2.71828...).
Similarly, you can implement log(x) using one of these series expansions:
log(1+x) = x - x2/2 + x3/3 - x4/4 + ...
or
log(1-x) = -1 * (x + x2/2 + x3/3 + x4/4 + ... )
But these series only converge for x in the interval -1 < x < 1. So for values
of a outside this range, you might have to use the identity
log(pq) = log(p) + log(q)
and do some repeated divisions by e (= 2.71828...) to bring a down into a range where
the series expansion converges. For example, if a=4, you'd have to take take x=3
to use the first formula, but 3 is outside the range of convergence. So we start
dividing out factors of e:
4/e = 1.47151...
log(4) = log(e*1.47151...) = 1 + log(1.47151...)
Now we can take x=.47151..., which is within the range of convergence, and evaluate log(1+x) using the series expansion.
Think about what a power function should do.
Mathematically: x^5 = x * x * x * x * x, or ((((x*x)*x)*x)*x)
Within your for loop, you can use the *= operator to achieve the operation that happens above.
How are you handling fractions? Java has no built-in fraction type; it stores decimals that would calculate the same way as integers (in other words, x * x works with both types). If you have a special class for fractions, your loop just needs two steps: one to multiply the numerator and one to multiply the denominator.
While reading up on powers on Wikipedia:
a^x = exp( x ln(a) ) for any real number x
Is this cheating?

How to limit a number to a range

I have this function to limit a rotation to the range from 0.0 to 360.0:
private float ClampRotation( float rotation ) {
while( rotation < 0.0f ) rotation += 360.0f;
while( rotation >= 360.0f ) rotation -= 360.0f;
return rotation;
}
This functions works great and it probably can't be more efficient, but I'm just wondering if there are a native Java function that can do the same?
The closest I get is Math.min/max, but it doesn't work as this. A rotation of -10.0 should output 350.0 and not 0.0 as min/max would do.
% (modulus) works on floating point values so use rotation % 360.0f (you will need to add 360.0 afterwards to negative numbers)
Use the modulus operator then account for values less than 0;
private float ClampRotation( float rotation ) {
rotation = rotation % 360f;
if (rotation < 0f) rotation += 360f;
return rotation;
}
it's just math.. you can do it like this:
private float ClampRotation( float rotation ) {
return rotation+360.0f*Math.ceil(-rotation/360.0f);
}
i'm pretty sure it's ok
You have the traditional implementation of wrapping angles which are less than an order of magnitude away the desired range.
Modulus is a bit weird for floating point - it returns negative for negative, so you still have to have a branch, and it involves a division, which is slower on some machines ( as in I've not found a machine where % is significantly less expensive than going round a loop with a couple of subtractions two or three times ).
If your values are within say -1000 to +1000, then your version is both clearer and faster. If your values are wider than that, go for a modulus based version. If it's very important, test both on your hardware with the value ranges you are going to use.

Moving between co-ordinates, Java Algorithms

Ok this question is going to be a little abstract.
I have an icon moving along a line which is represented by a series of coordinates stored in a vector, and I am iterating through them. The distance between coordinates is variable. So sometimes the icon will move slowly and smoothly, and others it will jump several 100 pixels at a time.
I am having trouble coming up with an algorithm to split up each set of coordinates it must travel between into a set of relative coordinates where the number is based on size, so that transition is smooth no matter how many co-ords are on a single line.
Any ideas would be much appreciated. Thanks :)
Take a look at this discussion of the Main Game Loop.
And here's a quote from that page:
At this step, updates to all the
objects in the game world are
calculated and performed. Usually, a
time step value is passed to all of
the update methods indicating how much
time has passed since the last update
...
You need to know 3 things:
how much time has elapsed since you last updated the position of your object?
what is the rate of movement of your object?
what is the direction (usually represented as a Ray) your object is moving?
From these, you can calculate the current position of the object.
If you want the object to move at a constant speed, I'd suggest a time-based model, where your object is actually moving at a speed (pixels/second). You can still get it to hit every point(ish) if you spline along a curve (such as a catmull-rom curve).
So you want to move from a initial point (x0/y0) to a end point (x1/y1) along a line by a variable number of steps but with a maximum distance for each step?
This could be done by something like this:
int stepdist = 10; // max pixels per step
double xdiff = x1 - x0;
double ydiff = y1 - y0;
double dist = sqrt( xdiff * xdiff + ydiff * ydiff );
int steps = (int) ( ( dist - 1 ) / stepdist );
if( steps > 0 )
{
xdiff /= steps;
ydiff /= steps;
while( --steps >= 0 )
{
x0 += xdiff;
y0 += ydiff;
moveTo( (int) x0, (int) y0 );
}
}
moveTo( (int) x1, (int) y1 );

Categories