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.
Related
I'm currently working on a raycaster, but I have one single problem.
Everything is set up, now I just need a bit mathematical help to answer following questions, and I couldn't find any simple explanation and we haven't learned such advanced vector stuff in school yet.
1] I have a line going from, lets say, (0,0,0) to (50,50,50)
now how can I find out if its intersects with a sphere, e.g (m = (10,10,5), r = 5)?
Yes, I searched around the whole internet, but ANYTHING is explained in vectors, but since they are not the same as lines that go from A to B, I never found anything helpful.
2] I have the same line from above, but this time I want to check if it intersects with a Cube, m = (25,30,50), it has a sidelenght of 5 units.
As before, please keep your explanation as simple as possible, an I'm working with Java by the way.
1) Sphere: The idea is to find the distance from the sphere's center to the line. If it is greater than the radius --> outside, vise versa - inside ( and if equal --> on the surface)
The equation of a line which goes through 2 point A, B is
x = A.x + (B.x - A.x)*t
y = A.y + (B.y - A.y)*t
z = A.z + (B.z - A.z)*t
The distance from the point M to a point in the line AB is:
d(t) = Math.sqrt((x - M.x) * (x - M.x) + (y - M.y) * (y - M.y) + (z - M.z) * (z - M.z))
The distance from the point M to the line AB is the shortest d(t)
If we set
g(t) = (x - M.x) * (x - M.x) + (y - M.y) * (y - M.y) + (z - M.z) * (z - M.z)
We will have
d(t) = Math.sqrt(g(t))
To find min(d(t)), we will try to find min(g(t)) instead (because the function derivative will be simpler). And to find min(g(t)), solve the equation derivative(g(t)) = 0
You will find
t = ((B.x - A.x)*(M.x - A.x) + (B.y - A.y)*(M.y - A.y) +
(B.z - A.z)*(M.z - A.z))/((B.x - A.x)*(B.x - A.x) + (B.y - A.y)*(B.y - A.y) + (B.z - A.z)*(B.z - A.z))
Then you can find d (or d*d)
2) Cube: The idea is to find the intersection of the line (AB) with each side of the cube and see if at least 1 side has the intersection inside the square
You don't say anything about whether the cube have sides parallel with coordinate axes, but let's use that case (the simplest :) )
The AB line's equation is the same as in 1)
x = A.x + (B.x - A.x)*t
y = A.y + (B.y - A.y)*t
z = A.z + (B.z - A.z)*t
The equations of all 8 sides are: (in your example, d = 5)
X = M.x - d
X = M.x + d
Y = M.y - d
Y = M.y + d
Z = M.z - d
Z = M.z + d
You should find the intersection between AB with each side of the cube
For example, AB with X = M.x -d
Solve the system of equations:
x = A.x + (B.x - A.x)*t
y = A.y + (B.y - A.y)*t
z = A.z + (B.z - A.z)*t
x = M.x - d
You will find:
x = M.x -d
t = (M.x -d - A.x)/(B.x - A.x) .. then find y, z
The point (x,y,z) is inside the side X = M.x -d of the cube if
M.y - d <= y <= M.y + d (and similar for z)
And do the same for other sides.
NOTE: If you want to check whether the segment [AB] intersects (reaches) the sphere/cube, you need to check one more conditions: The intersection is in the segment [AB]
min(A.x, B.x) <= x <= max(A.x, B.x)
min(A.y, B.y) <= y <= max(A.y, B.y)
..
Hope it can help you!
Consider a city where the streets are perfectly laid out to form an infinite square grid. In this city finding the shortest path between two given points (an origin and a destination) is much easier than in other more complex cities. As a new Uber developer, you are tasked to create an algorithm that does this calculation.
Given user's departure and destination coordinates, each of them located on some street, find the length of the shortest route between them assuming that cars can only move along the streets. You are guaranteed that at least one of the coordinates is an integer.
I am struggling a little to figure out the logic here. There are many cases and I don't know how to accommodate them all. This is what I have so far
double perfectCity(double[] departure, double[] destination) {
double yDist = Math.abs(destination[1]-departure[1]);
double xDist = Math.abs(departure[1] - departure[0] + departure[1]-destination[0]);
return xDist + yDist;
}
The algorithm is very simple if the inputs are integers, just find the absolute value between the x and y coordinates and then add them together. This is called the Manhattan distance.
int distance = Math.abs(x1 - x2) + Math.abs(y1 - y2);
With doubles, it is almost exactly the same, except for one situation. Here are some possibilities:
Both points have integer coordinates
One point has integer coordinates, and the other point has only one integer coordinate
Both points have only one integer coordinate, but they are on different axes.
Both points have only one integer coordinate, and they are on the same axis.
Possibilities 1-3 all work fine using the same algorithm as for finding distance with integers, except #4 has the possibility of the axis in common being on the same block.
For example, if the inputs were: {x: 0.5, y: 2} and {x: 0.5, y: 3} you would have to travel horizontally, vertically, and then backwards horizontally again in order to reach the destination. This is different from inputs of {x: 0.5, y: 2} and {x: 1.5, y: 3} because there is no need to travel backwards on the same axis.
So you can use the normal algorithm in all cases except for the case of when both of the Xs or Ys have floating-point values and have the same floor-ed value.
Your code should look something like this.
import static java.lang.Math.*;
public static double perfectCity(double x1, double y1, double x2, double y2) {
double xDist = abs(x1 - x2);
double yDist = abs(y1 - y2);
if (floor(x1) != x1 && floor(x2) != x2 && // both Xs are doubles
floor(x1) == floor(x2) && // on the same block
y1 != y2) { // not on the same street
xDist = min(abs(x1 - floor(x1) + x2 - floor(x2)),
abs(x1 - ceil(x1) + x2 - ceil(x2)));
} else if (floor(y1) != y1 && floor(y2) != y2 && // both Ys are doubles
floor(y1) == floor(y2) && // on the same block
x1 != x2) { // not on the same street
yDist = min(abs(y1 - floor(y1) + y2 - floor(y2)),
abs(y1 - ceil(y1) + y2 - ceil(y2)));
}
return xDist + yDist;
}
This can be much further simplified by using a helper function to calculate each axis separately.
public static double perfectCity(double x1, double y1, double x2, double y2) {
return travelOnAxis(x1, x2, y1 == y2) + travelOnAxis(y1, y2, x1 == x2);
}
private static double travelOnAxis(double from, double to, boolean travelIsStraight) {
if (Math.floor(from) == Math.floor(to) && !travelIsStraight) {
double dist = Math.abs((from % 1) + (to % 1));
return Math.min(dist, 2 - dist);
} else {
return Math.abs(from - to);
}
}
I used the trick with 2 - dist here because it's the same as calculating
Math.abs((1 - (from % 1)) + (1 - (to % 1)))
which is the same as
Math.abs(from - Math.ceil(from) + to - Math.ceil(to))
If this is a square grid, you can consider the x and y coordinates separately; the minimum distance is the sum of the minumum distances in the two directions.
In the p-direction (either x or y), you have to move from p1 to p2. From p1, you can either move to floor(p1) or ceil(p1) to get to a road (which may be equal, if p1 is an integer); from there, you can move to either floor(p2) or ceil(p2), the road on which p2 is located; from there, you can move to p2.
So, the minimum distance in the p-direction is
min(abs(p1 - ceil(p1) ) + abs(ceil(p1) - floor(p2)) + abs(floor(p2) - p2), # (1)
abs(p1 - floor(p1)) + abs(floor(p1) - ceil(p2) ) + abs(ceil(p2) - p2), # (2)
abs(p1 - floor(p1)) + abs(floor(p1) - floor(p2)) + abs(floor(p2) - p2), # (3)
abs(p1 - ceil(p1) ) + abs(ceil(p1) - ceil(p2) ) + abs(ceil(p2) - p2)) # (4)
So you can just calculate this independently for the x and y directions, and add.
To illustrate this (abbreviating floor and ceil as f and p respectively):
f(p1) p1 c(p1)
+---O>>>>+>>>>>>>>+
.
.
+>>>O----+
f(p2) p2 c(p2)
--------------------------------> p axis
The shortest route is indicated here with >. The .s are on the shortest route, but since that part of the route is orthogonal to the p direction, it "doesn't count" towards the minimum distance in that direction.
The minimum route shown here, p1 -> c(p1) -> f(p2) -> p2, is Case 1 above.
It should not be hard to visualize swapping p1 and p2, in which case the minimum route is to go from p1 ->f(p1) -> c(p2) -> p2 (Case 2).
The case of pN == f(pN) == c(pN) is not very different; then, the part of the expression abs(pN - f(pN)) or abs(pN - c(pN)) is just zero.
The slightly different case is where f(p1) == f(p2):
f(p1) p1 c(p1) f(p1) p1 c(p1)
+---O>>>>+ +<<<O----+
. .
. .
+-----O<<+ +>>>>>O--+
f(p2) p2 c(p2) f(p2) p2 c(p2)
--------------------------------> p axis
In this case, the minimum route can either be p1 -> f(p1) -> f(p2) -> p2 or p1 -> c(p1) -> c(p2) -> p2 (which are Cases 3 and 4, respectively).
As mentioned by 4castle, the problem is trivial if only integers are considered for input. You would never have to "move back" after having "moved forward" in that case since you would always reach your destinaton in a single move.
But since, at most one floating point number needs to be considered for each of departure/destination, we need to consider 3 cases, (warning: lengthy explanation). Below is a python2 implementation with explanations.
x co-ordinates of both departure and destination are the same and are not floating point numbers. In this case, the shortest distance is simply the absolute difference between y co-ordinates. The same logic applies vice-versa.
import math
class Location():
def __init__(self, cord):
self.x = cord[0]
self.y = cord[1]
def perfectCity(departure, destination):
l1 = Location(departure)
l2 = Location(destination)
if l1.x == l2.x and float(l1.x).is_integer() and float(l2.x).is_integer():
return abs(l1.y-l2.y)
if l1.y == l2.y and float(l1.y).is_integer() and float(l2.y).is_integer():
return abs(l1.x-l2.x)
When one of the co-ordinates in the departure is a floating point, then:
If x co-ordinate is floating point, we can move backwards(round down) or move front(round up).
If y co-ordinate is floating point, we can either move down (round down) or move up (round up).
The above logic should work even when there is no floating point co-ordinate since we move in either direction by zero units.
Once we calculate these, we just choose the minimum among those like below,
return min(calc_round_up_dist(l1, l2), cal_round_down_dist(l1, l2))
Lets take an example of (0.4, 1) and (0.9, 3) for below calculations.
While calculating the round_up we need to calculate 3 distances:
round_up_distance: difference between the rounded up value of the floating point co-ordinate and the original floating point co-ordinate. We return zero if there is no floating point co-ordinate. 1 - 0.4 = 0.6 in the above example
non_floating_point difference: difference between the non floating point co-ordinate of departure and the corresponding co-ordinate of destination ( note that this might be floating point or not a floating point abs(3-1) = 2 in the above example
Difference between departure's floating point counterpart in the destination co-ordinate 0.9 in the above case and the new value of departure's floating point after rounding up, 0.4 + 0.6(this is the round_up distance) = 1.0, i.e. abs(0.9 - 1.0) = 0.1
Adding all the 3 above we get 0.6 + 2 + .1 = 2.7 which is the shortest distance.
Corresponding calculation needs to be done for rounding down. And we pick the minimum among both. The code for round_up and round_down is as below,
import math
class Location():
def __init__(self, cord):
self.x = cord[0]
self.y = cord[1]
def floating_point_round_up(self):
if not float(self.x).is_integer():
return math.ceil(self.x) - self.x
if not float(self.y).is_integer():
return math.ceil(self.y) - self.y
return 0
def floating_point_round_down(self):
if not float(self.x).is_integer():
return self.x - math.floor(self.x)
if not float(self.y).is_integer():
return self.y - math.floor(self.y)
return 0
def non_floating_point_diff(self, obj):
if not float(self.x).is_integer():
return abs(self.y - obj.y)
if not float(self.y).is_integer():
return abs(self.x - obj.x)
return abs(self.y - obj.y)
def floating_point_counterpart(self, obj):
if not float(self.x).is_integer():
return obj.x
if not float(self.y).is_integer():
return obj.y
return obj.x
def floating_point(self):
if not float(self.x).is_integer():
return self.x
if not float(self.y).is_integer():
return self.y
return self.x
Round up and down functions are as below,
def calc_round_up_dist(l1, l2):
dist = l1.floating_point_round_up()
diff = l1.non_floating_point_diff(l2)
floating_point_counterpart = l1.floating_point_counterpart(l2)
new_val = dist + l1.floating_point()
return dist + diff + abs(new_val - floating_point_counterpart)
def cal_round_down_dist(l1, l2):
dist = l1.floating_point_round_down()
diff = l1.non_floating_point_diff(l2)
floating_point_counterpart = l1.floating_point_counterpart(l2)
new_val = l1.floating_point() - dist
return dist + diff + abs(floating_point_counterpart - new_val)
Finally the main function that calls the above methods,
def perfectCity(departure, destination):
l1 = Location(departure)
l2 = Location(destination)
if l1.x == l2.x and float(l1.x).is_integer() and float(l2.x).is_integer():
return abs(l1.y-l2.y)
if l1.y == l2.y and float(l1.y).is_integer() and float(l2.y).is_integer():
return abs(l1.x-l2.x)
return min(calc_round_up_dist(l1, l2), cal_round_down_dist(l1, l2))
This is a practice question on CodeSignal:
https://app.codesignal.com/company-challenges/uber/gsjPcfsuNavxhsQQ7
def solution(departure, destination):
# go to the closest integer
# I can only travel the path of an integer
# if the number is a float I need to travel to an integer first
# then travel to the destination
x1, y1 = departure
x2, y2 = destination
res = 0
# check if the coordinations are integers
a = list(map(isInteger, departure))
b = list(map(isInteger, destination))
# if all are integers or if the corresponding elements are different
if a[0] ^ b[0] or (a[0] and a[1] and b[0] and b[1]):
return abs(x1-x2) + abs(y1-y2)
if a[0]:
res += abs(x2-x1)
# cloest distance from y1 to y2
res += getClosest(y1, y2)
else:
res += abs(y2-y1)
# closes distance from x1 to x2
res += getClosest(x1, x2)
return res
def getClosest(y1, y2):
cand1 = math.floor(y1)
cand2 = math.ceil(y1)
# find the integer closer to y1 to move to
res1 = abs(y1-cand1) + abs(cand1-y2)
res2 = abs(y1-cand2) + abs(cand2-y2)
return min(res1, res2)
def isInteger(n):
return n == round(n)
I really suck at math. No, better explanation: I don't know how to interpret mathematical notation. My brain just cant interpret it. That's why I come to the programming community for help "translating" math into a language I do understand.
I have two sets of coordinates in 3d space representing the line of sight.
Vector1(eyes) x=10 y=10 z=4
Vector2(lookingat) x=10 y=8 z=4.785
How do I calculate a point with these double values beyond the looking at value? for example, what lies 2 points beyond the line we are looking it? what location in space would that be?
In short:
How do I extrapolate a given point beyond the line made up by two vectors with given double value along the line.
a known
\
\
\
b known
?
? + 3
?
c what is this value...
Edit
With the help of the answer of #Thrustmaster I came up with this wonderfull solution. Thanks a lot :D
private Vec3 calculateLine(Vec3 x1, Vec3 x2, double distance) {
double length = Math.sqrt(multiply(x2.xCoord - x1.xCoord) + multiply((x2.yCoord - x1.yCoord)) + multiply((x2.zCoord - x1.zCoord)));
double unitSlopeX = (x2.xCoord-x1.xCoord) / length;
double unitSlopeY = (x2.yCoord-x1.yCoord) / length;
double unitSlopeZ = (x2.zCoord-x1.zCoord) / length;
double x = x1.xCoord + unitSlopeX * distance;
double y = x1.yCoord + unitSlopeY * distance;
double z = x1.zCoord + unitSlopeZ * distance;
return Vec3.createVectorHelper(x, y, x);
}
private double multiply(double one) {
return one * one;
}
You need to start looking to basic 3D coordinate geometry.
In 3D, the equation can be written as:
x = x1 + unitSlopeX * distance
y = y1 + unitSlopeY * distance
z = z1 + unitSlopeZ * distance
.. where (x1,y1,z1) can be any point on the line; in this case (10,10,4).
Next set of unknowns is all 3 unitSlopes. To calculate it, simply subtract the two points (this will ive you a vector), and divide by the length of the vector.
length = sqrt((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2)
unitSlopeX = (x2-x1) / length
unitSlopeY = (y2-y1) / length
unitSlopeZ = (z2-z1) / length
Now, to finally, get your third coordinate, simply plug in distance (any value) into the three equations at the beginning of this post.
In vector notation:
V = V1 + t * (V2 - V1) / | V2 - V1 |
.. where t is any real number.
I'm practicing for an exam, and I'm doing one of the practice problems. I have a method that takes two arguments: one for the radius of a circle, and one for the number of dots to place within that circle. The method is below:
private void drawDots(int radius, int numDots){
double ycord;
double xcord;
for(int q = 0; q < numDots; q++){
ycord = -radius + random()*(radius+radius+1);
xcord = pow((pow(radius,2)-pow(ycord,2)),0.5);
turt.moveTo(xcord,ycord);
turt.penDown();
turt.forward(0);
turt.penUp();
}
}
turt is an object I'm using to draw with, and penDown()/penUp() is placing and removing the object from the canvas respectively.
I'm trying to define the x-coordinate and y-coordinate of the turt object to stay within a radius. Say the radius is 100, and the number of dots is 200, how do I keep the object within that radius?
The question states that:
"To constain the dots to a circle of radius r, a random y-coord in the interval -r, r is chosen. To x-coord is then randomly chosen in the interval -b, b, where b = sqrt(r^2 - y^2)."
I'm just not sure how to make sense of this math. The code above was my best attempt, but the output is strange.
Here is my failed output:
The distance from the center (0,0) to a dot must be less than the radius of the circle, r. The distance can be expressed as sqrt(x² + y²). Therefore, if you choose your y coordinate randomly between [-r, r], you just have to make sure that your x coordinate respects the previous equation, hence your math.
Demonstration
sqrt(x² + y²) < r
x² + y² < r²
x² < r² - y²
x < sqrt(r² - y²)
#
Your algorithm should be as follows. Once you chose the y coordinate, you can randomly choose x as long as it respects the distance constraint.
private void drawDots(int radius, int numDots){
double y;
double x;
double xMax;
for (int q = 0; q < numDots; q++){
// y is chosen randomly
y = -radius + random() * (radius + radius + 1);
// x must respect x² + y² < r²
xMax = pow((pow(radius,2)-pow(ycord,2)), 0.5);
x = random() * 2 * xMax - xMax;
turt.moveTo(x, y);
turt.penDown();
turt.forward(0);
turt.penUp();
}
}
Take a look at the documentation for random, you will see by default it produces a number between 0 and 1.
Basically this means that the expression you are looking for is:
ycord=-radius+random()*(radius*2);
This gives you a point on the y axis between -radius and radius (consider if the random() returns 0 you get -radius, it it returns 1 you get -radius+(2*radius())=radius.
You calculation for the x co-ordinate is correct but it gives you the x coordinate point on the circle (lets call it b). I suspect you want to use a new random to select an x co-ordinate between b and -b.
At present you are drawing points on the circle, not inside it. That is because you are not following the guideline correctly.
b = pow((pow(radius,2)-pow(ycord,2)),0.5); // this should be b
xcord = -b + random()*(b+b);
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