Slowly reduce the number - java

I have a number that is being increased by an increment on each step. Let's assume that start number is 0 and increment is 100.
On step #5 and later I want to start decreasing the base increment (100). The increment should be decreased smoothly and at step #10 it equals 0.
Here is a graph that basically explains what am I trying to do (y - increment, x - step).
Code representation:
// x - step
// y - increment
var value = 0;
for(var x = 0; x < 10; x++) {
var y = 100;
if(x > 5) {
// y = ???
}
value += y;
}
So the question is how to represent this? It would be also great to have an option to modify the smoothness of this arc.
Thank you!

This will give you a perfect quarter cirle that starts at (5|100) and ends at (10|0).
if (x > 5) {
y = 100 * Math.sqrt( 1 - Math.pow(((x - 5) / 5), 2) );
}
http://fooplot.com/plot/2i8hy2twl4
Explanation (optional)
Warning! May contain mathematics!
Let's start with a simpler case, a quarter circle with a radius of 1 and its center is (0|0). We know that x² + y² = r²(Pythagorean theorem). x and r are known, so we can calculate y this way: y = sqrt(r² - x²). Since our radius is always 1 and 1² is equal to 1, we can break it down to this:
y = sqrt(1 - x²)
The value of y ranges from 0 to 1. We want it to range from 0 to 100 though. To achieve this, we simply multiply the right side by 100.
y = 100 * sqrt(1 - x²)
^^^^^^
To shift the entire thing 5 to the right, we need to subtract 5 from x.
y = 100 * sqrt(1 - (x - 5)²)
^^^^^
Also, we want to stretch it to the right, so that our quarter circle ranges from x = 5 to x = 10 and not to x = 6, so wie divide (x - 5) by 5.
y = 100 * sqrt(1 - ((x - 5) / 5)^2)
^^^^
Everything to do now is to replace sqrt by Math.sqrt and ^2 by Math.pow to make it valid Javascript code.
y = 100 * Math.sqrt( 1 - Math.pow(((x - 5) / 5), 2) );

If that curve is a quarter circle, then the equation that you want is
y = 20 * Math.sqrt(x * (10 - x));
If it's not a quarter circle, then it's anyone's guess.

if (x<=5)
y = 100;
else if (x>=10)
y = 0;
else {
double radius = 100;
double offset = (x-5)*20;
y = Math.sqrt(raidus*radius - offset*offset);
}
http://fooplot.com/plot/offuyxbfzu

Related

Trying to get divisor that produces a quotient within a range

This is for a visualization I am working on. I want to divide a rectangle in N equal parts. I want these parts to have a width of say (min. 1px, max 1.5px), depending on the width of the rectangle and I want this division to end with a remainder of 0 (so I don't have a larger than the rest part).
I have tried implementing Modulo: https://processing.org/reference/modulo.html but I am not sure this is the correct way. Any ideas?
//Generates coordinates within each line.
for (int j = 0; j < line_coordinates.length; j++) {
//Positions start of line draw on random X coordinate.
float xv = component_x1 + (j * (component_length / line_coordinates.length+1));
float yv = line_height;
//Defines available with for each item in a component.
float item_availablewidth = component_length / line_coordinates.length+1;
//Creates vector with X coordinate and Y noise affected coordinate.
line_coordinates[j] = new PVector(xv, y);
rectMode(CENTER);
noStroke();
fill(232, 45, 34);
rect(line_coordinates[j].x,
line_coordinates[j].y - (line_height / 2),
item_availablewidth * item_randomwidthcoefficient,
line_height);
println("line_coordinates[j].x1",
line_coordinates[j].x - ((item_availablewidth * item_randomwidthcoefficient) / 2)); //This is where X starts.
println("line_coordinates[j].x2",
line_coordinates[j].x + ((item_availablewidth * item_randomwidthcoefficient) / 2)); //This is where X is supposed to end.
//This is the first method I tried but I found out this separation needs to be dynamic.
float drawnline_separation = 2;
float drawnline_total = (item_availablewidth * item_randomwidthcoefficient) / drawnline_separation;
println("drawnline_total",
drawnline_total);
//For loop divides each item in vertical -axidrawable- lines separating them by a max
for (int l = 0; l <= drawnline_total; l++) {
float drawnline_x = lerp(line_coordinates[j].x - ((item_availablewidth * item_randomwidthcoefficient) / 2),
line_coordinates[j].x + ((item_availablewidth * item_randomwidthcoefficient) / 2),
l/drawnline_total);
println("drawnline_x", drawnline_x);
stroke(23);
noFill();
//Draws line.
line(drawnline_x,
line_coordinates[j].y,
drawnline_x,
line_coordinates[j].y + 25 );
}
}
//This is the print I am getting.
line_coordinates[j].x1 346.42535
line_coordinates[j].x2 353.44092
drawnline_total 3.5077777
drawnline_x 346.42535
drawnline_x 348.42535
drawnline_x 350.42535
drawnline_x 352.42535
I hope I am being clear! Please let me know if my explanation is very confusing.

I am trying to calculate sine of an angle without using the Math.sin() in java

I am trying to calculate sine of an angle without using the Math.sin(). I got stuck in it's equation as I keep getting the wrong results
note I have a method that changes the angle from degrees to radians
public static double sin(double x, int precision) {
//this method is simply the sine function
double answer = 1, power = 1;
int n = 2,factorial = 1;
while (n<=precision) {
power = (power * x * x *-1) +1 ;
factorial = (factorial * (n +1))* (n-1);
answer = answer + ((power/factorial ));
n = n + 2;
}
return answer;
}
It looks like you're attempting to calculate the sine of angle given in radians using the Maclaurin series, a special case of Taylor series.
sin(x) = x - x^3/3! + x^5/5! - x^7/7! + ...
Your initial answer is 1 when it should be x. Your initial power is 1 when it should be x also.
double answer = x, power = x;
For some reason you're adding one to the power part of the result when you shouldn't be.
power = (power * x * x * -1);
You'll also need to fix your factorial calculation. Multiply by n + 1 and n, not n + 1 and n - 1.
factorial = (factorial * (n + 1)) * (n);
With these fixes, testing:
for (double angle = 0; angle <= Math.PI; angle += Math.PI / 4)
{
System.out.println("sin(" + angle + ") = " + sin(angle, 10));
}
The results are pretty good considering the limitations of precision for floating point arithmetic.
sin(0.0) = 0.0
sin(0.7853981633974483) = 0.7071067811796194
sin(1.5707963267948966) = 0.999999943741051
sin(2.356194490192345) = 0.7070959900908971
sin(3.141592653589793) = -4.4516023820965686E-4
Note that this will get more inaccurate as the values of x get larger, not just because of the inaccuracy to represent pi, but also because of the floating point calculations for adding and subtracting large values.

java- making a path more dense?

I have an array list of points in JAVA.
I want to add more points so the path is more dense.
How should I try to do this?
I made this image to explain better
Let's consider two points from your 2D-polyline A (x1, y1) and B (x2, y2).
We can build straight-line equation using these two points A and B.
The common form of the equation is: y = k*x + b, where k and b are constants.
Using A and B coords we build an equation system:
k*x1 + b = y1
k*x2 + b = y2
Solving this equation we get k and b constants and therefore we have the line equation built.
After that, substitute X coordinates to this equation and you get Y coordinates.
So, we need to find dots between A and B.
And we substitute x1 + 1 as X to this equation, to get relevant Y coordinate.
After that we substitute x1 + 2 as X to this equation to get the relevant Y coordinate and so on, until you get X2 coordinate of the dot B.
Consider the following example.
We have A (2, 2) and B (5, 3)
Building the equation system:
2 * k + b = 2
5 * k + b = 3
b = 2 - 2 * k
5 * k + 2 - 2 * k = 3
3 * k + 2 = 3
3 * k = 1
k = 1/3
b = 2 - 2/3
b = 4/3
and our A-B line equation is:
y = x/3 + 4/3
let's find dots between A and B.
We increase x coordinate of the dot A to 1, and are going to find Y coordinate of that dot.
x = 3
y = 1 + 4/3 = 7/3
Now, get the next dot after that, using x = 4
x = 4
y = 4/3 + 4/3 = 8/3
Dot B has x coordinate equal to 5, just checking:
x = 5
y = 5/3 + 4/3 = 3
correct!
That's it.

get X,Y coords of an isometric cell by its id

I have an isometric grid that is numbered like the image above. I need a function that returns X,Y coords from a given cell number, without using any kind of loops.
I've literally spent hours trying to figure this out, here is what I came up with so far:
public static Coords getXY(int cellID)
{
final double CELL_WIDTH = 53;
final double LEVEL_HEIGHT = 27;
final int gridWidth = 6;
boolean isYellowRow = cellID % (gridWidth*2-1) <= gridWidth;
double x = ((cellID % gridWidth) + 1) + (isYellowRow ? 0 : 0.5 );
double y = cellID / (gridWidth*2-1);
y = Math.round(y) + (isYellowRow ? 1 : 0);
System.out.println(x+", "+y);
x *= CELL_WIDTH;
y *= LEVEL_HEIGHT;
System.out.println(x+", "+y);
return Coords(x, y);
}
It's messy not working and isn't complete yet, I'v spent way more time than I should on this and I'm still unable to solve it, so I'm asking your help please.
Some examples of expected results:
getXY(1); // Should return: 53, 27
getXY(2); // Should return: 106, 27
getXY(6); // Should return: 26.5, 40.5 (40.5 is because +=cellHeight/2..)
getXY(7); // Should return: 79.5, 40.5
getXY(12); // Should return: 53, 54
Try this
int n; // cell number
double x, y; // coordinates of top vertex of cell
double CELL_WIDTH = 53;
double LEVEL_HEIGHT = 27;
x = (double)(((n-1)%11) * CELL_WIDTH) - (((n-1)%11 > 4) ? 5.5d*CELL_WIDTH : 0d);
y = (double)((n-1)/11) * LEVEL_HEIGHT * 2d + (((n-1)%11 > 4) ? LEVEL_HEIGHT/2 : 0d);
This places (0,0) at the top vertex of the first cell. Add offsets to move (0,0) wherever you want it to be.
The approach:
The repetitive pattern has period 11, in two rows. So, first calculate the horizontal offset as if the 11 cells were in a straight line: ((n-1)%11) * CELL_WIDTH. Then realize that if the cell is on the second line, the horizontal offset will be left by 5-1/2 cells: - ((n-1)%11 > 4) ? 5.5d*CELL_WIDTH : 0d. Do the same for the vertical offsets and throw in appropriate casting so the result is floating point (since you seem to want half-pixel answers).

Check is a point (x,y) is between two points drawn on a straight line

I have drawn a line between two points A(x,y)---B(x,y)
Now I have a third point C(x,y). I want to know that if C lies on the line which is drawn between A and B.
I want to do it in java language. I have found couple of answers similar to this. But, all have some problems and no one is perfect.
if (distance(A, C) + distance(B, C) == distance(A, B))
return true; // C is on the line.
return false; // C is not on the line.
or just:
return distance(A, C) + distance(B, C) == distance(A, B);
The way this works is rather simple. If C lies on the AB line, you'll get the following scenario:
A-C------B
and, regardless of where it lies on that line, dist(AC) + dist(CB) == dist(AB). For any other case, you have a triangle of some description and 'dist(AC) + dist(CB) > dist(AB)':
A-----B
\ /
\ /
C
In fact, this even works if C lies on the extrapolated line:
C---A-------B
provided that the distances are kept unsigned. The distance dist(AB) can be calculated as:
___________________________
/ 2 2
V (A.x - B.x) + (A.y - B.y)
Keep in mind the inherent limitations (limited precision) of floating point operations. It's possible that you may need to opt for a "close enough" test (say, less than one part per million error) to ensure correct functioning of the equality.
ATTENTION! Math-only!
You can try this formula. Put your A(x1, y1) and B(x2, y2) coordinates to formula, then you'll get something like
y = k*x + b; // k and b - numbers
Then, any point which will satisfy this equation, will lie on your line.
To check that C(x, y) is between A(x1, y1) and B(x2, y2), check this: (x1<x<x2 && y1<y<y2) || (x1>x>x2 && y1>y>y2).
Example
A(2,3) B(6,5)
The equation of line:
(y - 3)/(5 - 3) = (x - 2)/(6 - 2)
(y - 3)/2 = (x - 2)/4
4*(y - 3) = 2*(x - 2)
4y - 12 = 2x - 4
4y = 2x + 8
y = 1/2 * x + 2; // equation of line. k = 1/2, b = 2;
Let's check if C(4,4) lies on this line.
2<4<6 & 3<4<5 // C between A and B
Now put C coordinates to equation:
4 = 1/2 * 4 + 2
4 = 2 + 2 // equal, C is on line AB
PS: as #paxdiablo wrote, you need to check if line is horizontal or vertical before calculating. Just check
y1 == y2 || x1 == x2
I believe the simplest is
// is BC inline with AC or visa-versa
public static boolean inLine(Point A, Point B, Point C) {
// if AC is vertical
if (A.x == C.x) return B.x == C.x;
// if AC is horizontal
if (A.y == C.y) return B.y == C.y;
// match the gradients
return (A.x - C.x)*(A.y - C.y) == (C.x - B.x)*(C.y - B.y);
}
You can calculate the gradient by taking the difference in the x values divided by the difference in the y values.
Note: there is a different test to see if C appears on the line between A and B if you draw it on a screen. Maths assumes that A, B, C are infinitely small points. Actually very small to within representation error.
The above answers are unnecessarily complicated. The simplest is as follows.
if (x-x1)/(x2-x1) = (y-y1)/(y2-y1) = alpha (a constant), then the point C(x,y) will lie on the line between pts 1 & 2.
If alpha < 0.0, then C is exterior to point 1.
If alpha > 1.0, then C is exterior to point 2.
Finally if alpha = [0,1.0], then C is interior to 1 & 2.
Hope this answer helps.
I think all the methods here have a pitfall, in that they are not dealing with rounding errors as rigorously as they could. Basically the methods described will tell you if your point is close enough to the line using some straightforward algorithm and that it will be more or less precise.
Why precision is important? Because it's the very problem presented by op. For a computer program there is no such thing as a point on a line, there is only point within an epsilon of a line and what that epsilon is needs to be documented.
Let's illustrate the problem. Using the distance comparison algorithm:
Let's say a segment goes from (0, 0) to (0, 2000), we are using floats in our application (which have around 7 decimal places of precision) and we test whether a point on (1E-6, 1000) is on the line or not.
The distance from either end of the segment to the point is 1000.0000000005 or 1000 + 5E-10, and, thus, the difference with the addition of the distance to and from the point is around 1E-9. But none of those values can be stored on a float with enough precission and the method will return true.
If we use a more precise method like calculating the distance to the closest point in the line, it returns a value that a float has enough precision to store and we could return false depending on the acceptable epsilon.
I used floats in the example but the same applies to any floating point type such as double.
One solution is to use BigDecimal and whichever method you want if incurring in performance and memory hit is not an issue.
A more precise method than comparing distances for floating points, and, more importantly, consistently precise, although at a higher computational cost, is calculating the distance to the closest point in the line.
Shortest distance between a point and a line segment
It looks like I'm splitting hairs but I had to deal with this problem before. It's an issue when chaining geometric operations. If you don't control what kind of precission loss you are dealing with, eventually you will run into difficult bugs that will force you to reason rigorously about the code in order to fix them.
An easy way to do that I believe would be the check the angle formed by the 3 points.
If the angle ACB is 180 degrees (or close to it,depending on how accurate you want to be) then the point C is between A and B.
I think this might help
How to check if a point lies on a line between 2 other points
That solution uses only integers given you only provide integers which removes some pitfalls as well
Here is my C# solution. I believe the Java equivalent will be almost identical.
Notes:
Method will only return true if the point is within the bounds of the line (it does not assume an infinite line).
It will handle vertical or horizontal lines.
It calculates the distance of the point being checked from the line so allows a tolerance to be passed to the method.
/// <summary>
/// Check if Point C is on the line AB
/// </summary>
public static bool IsOnLine(Point A, Point B, Point C, double tolerance)
{
double minX = Math.Min(A.X, B.X) - tolerance;
double maxX = Math.Max(A.X, B.X) + tolerance;
double minY = Math.Min(A.Y, B.Y) - tolerance;
double maxY = Math.Max(A.Y, B.Y) + tolerance;
//Check C is within the bounds of the line
if (C.X >= maxX || C.X <= minX || C.Y <= minY || C.Y >= maxY)
{
return false;
}
// Check for when AB is vertical
if (A.X == B.X)
{
if (Math.Abs(A.X - C.X) >= tolerance)
{
return false;
}
return true;
}
// Check for when AB is horizontal
if (A.Y == B.Y)
{
if (Math.Abs(A.Y - C.Y) >= tolerance)
{
return false;
}
return true;
}
// Check istance of the point form the line
double distFromLine = Math.Abs(((B.X - A.X)*(A.Y - C.Y))-((A.X - C.X)*(B.Y - A.Y))) / Math.Sqrt((B.X - A.X) * (B.X - A.X) + (B.Y - A.Y) * (B.Y - A.Y));
if (distFromLine >= tolerance)
{
return false;
}
else
{
return true;
}
}
def DistBetwPoints(p1, p2):
return math.sqrt( (p2[0] - p1[0])**2 + (p2[1] - p1[1])**2 )
# "Check if point C is between line endpoints A and B"
def PointBetwPoints(A, B, C):
dist_line_endp = DistBetwPoints(A,B)
if DistBetwPoints(A,C)>dist_line_endp: return 1
elif DistBetwPoints(B,C)>dist_line_endp: return 1
else: return 0
Here is a JavaScript function I made. You pass it three points (three objects with an x and y property). Points 1 and 2 define your line, and point 3 is the point you are testing.
You will receive an object back with some useful info:
on_projected_line - If pt3 lies anywhere on the line including outside the points.
on_line - If pt3 lies on the line and between or on pt1 and pt2.
x_between - If pt3 is between or on the x bounds.
y_between - If pt3 is between or on the y bounds.
between - If x_between and y_between are both true.
/**
* #description Check if pt3 is on line defined by pt1 and pt2.
* #param {Object} pt1 The first point defining the line.
* #param {float} pt1.x
* #param {float} pt1.y
* #param {Object} pt2 The second point defining the line.
* #param {float} pt2.x
* #param {float} pt2.y
* #param {Object} pt3 The point to test.
* #param {float} pt3.x
* #param {float} pt3.y
*/
function pointOnLine(pt1, pt2, pt3) {
const result = {
on_projected_line: true,
on_line: false,
between_both: false,
between_x: false,
between_y: false,
};
// Determine if on line interior or exterior
const x = (pt3.x - pt1.x) / (pt2.x - pt1.x);
const y = (pt3.y - pt1.y) / (pt2.y - pt1.y);
// Check if on line equation
result.on_projected_line = x === y;
// Check within x bounds
if (
(pt1.x <= pt3.x && pt3.x <= pt2.x) ||
(pt2.x <= pt3.x && pt3.x <= pt1.x)
) {
result.between_x = true;
}
// Check within y bounds
if (
(pt1.y <= pt3.y && pt3.y <= pt2.y) ||
(pt2.y <= pt3.y && pt3.y <= pt1.y)
) {
result.between_y = true;
}
result.between_both = result.between_x && result.between_y;
result.on_line = result.on_projected_line && result.between_both;
return result;
}
console.log("pointOnLine({x: 0, y: 0}, {x: 1, y: 1}, {x: 2, y: 2})")
console.log(pointOnLine({x: 0, y: 0}, {x: 1, y: 1}, {x: 2, y: 2}))
console.log("pointOnLine({x: 0, y: 0}, {x: 1, y: 1}, {x: 0.5, y: 0.5})")
console.log(pointOnLine({x: 0, y: 0}, {x: 1, y: 1}, {x: 0.5, y: 0.5}))
if ( (ymid - y1) * (x2-x1) == (xmid - x1) * (y2-y1) ) **is true, Z lies on line AB**
Start Point : A (x1, y1),
End Point : B (x2, y2),
Point That is on Line AB or Not : Z (xmid, ymid)
I just condensed everyone's answers and this formula works the best for me.
It avoids division by zero
No distance calculation required
Simple to implement
Edit: In case you are dealing with floats, which you most probably are,
use this:
if( (ymid - y1) * (x2-x1) - (xmid - x1) * (y2-y1) < DELTA )
where the tolerance DELTA is a value close to zero.
I usually set it to 0.05

Categories