Distribute items around circle with math - Flutter code - flutter

I have a set of elements and I need to distribute them on a circular curve like the one in the picture below, so that the maximum possible number of elements is 10 and the minimum number is 3.
I need a mathematical equation or any other method in order to distribute these elements in a circular shape, with the Dart language.
Thank

I don't know anything about Dart, but this is how you can solve it mathematically:
(x,y): center of the circle
r: radius of the circle
a: start angle of the distribution in radians
b: end angle of the distribution in radians
n: number of elements
The element with index i should be positioned at:
x_new = x + r * cos(a + i * (b - a) / (max(2, n - 1)))
y_new = y + r * sin(a + i * (b - a) / (max(2, n - 1)))

Related

Calculate point at distance between two coordinates

Given two points A and B and a distance d, I'm trying to calculate a point C between A and B and at distance d from point A.
I was thinking on using Thales theoreme, but is there a better/simpler solution?
Cheers!
Sure the Thales' (Intercept) Theorem is a suitable method, and a degenerate case of that theorem applies when one of the two intersecting lines is a coordinate axis (for example: latA)
So, the steps would be:
set a variable to the delta rise: deltalat = latB - latA
set a variable to the delta run: deltalng = lngB - lngA
compute the full (pythagorean) distance from A to B: dist = sqrt(deltalat*deltalat + deltalng*deltalng)
compute angle from horizontal: ang= arcsin(deltalat/dist)
compute new lat: latC = latA + (d * sin(ang))
compute new lng: lngC = lngA + (d * cos(ang))
I went through that a bit quickly in my head, so double-check my trig, please.

Getting position of a coordinate on the surface of a sphere

There is an object A. I want to create a object B. I'm trying to avoid that A covers B:
I have thinking how to achieve that. Take a look of the following drawing:
I have been thinking in a solution in a math - geometry way before searching for some Unity3D function to solve the problem. I have realise A and B would be on the same surface if the camera is within a sphere with radius c-A. So I guess the solution can be related to get a point at a B at a distance A-B from A on the surface of the sphere with radius c-A. Does it has sense? Any other idea? How to do it with maths and Unity?
What you are describing is a ring on the sphere's surface whose plane is perpendicular to the direction c-A.
This is fairly simple to compute. First we need to find 2 perpendicular vectors to c-A (we'll call this d):
Call the vector "c-A" = d, the radius of the sphere R = abs(d) and the distance "A-B" = D.
If d.X / R < 0.5, set a temporary vector w = X, else set w = Y.
Compute the first perpendicular vector u = normalize(cross(w, d)).
Compute the second one v = normalize(cross(d, u)).
The center point of this ring is given by c + d * cos(D / R). From here we can generate any point on the ring with
p(t) = c + d * cos(D / R) + u * cos(t) + v * sin(t) , 0 ≤ t ≤ 2π
UPDATE:

Point of intersection between two vectors when the direction of one vector is not known

Problem: I have two vectors. I know the starting point of one vector, its direction, its magnitude. I know the starting point of the other vector and its magnitude. I need to find the direction of second vector as well as the position of intersection.
Vector A: Vector B:
Position = Known Position = Known
Direction= Known Direction= UNKNOWN
Magnitude= Known Magnitude= Known
To Find: Point of intersection.
Is it possible to find the point of intersection, with the given parameters? If so then how?
Application: I want to find the position where a player would be found based on the velocity he is moving, and shoot a bullet at him at the moment he would be found, taking into account the time taken for the bullet to reach that virtual target position.
Following on from the comments I'm going to take a leap here and answer your ultimate question directly.
Say the player is, at the initial time, at a point p and travelling with velocity v; your gun is at position q and shoots a bullet in any direction at speed s:
The length of OP is vΔt and that of Q sΔt. The angle a is given by the dot product:
We can then use the cosine rule to solve for Δt:
Written in this form, we can easily see that it is a quadratic equation, and thus directly solve for Δt using the Quadratic formula:
There are a few cases we need to consider here:
v < s: need to take the positive root only as otherwise we would get negative time.
v > s and dot(PQ, s) < 0: the bullet will never catch the player.
v > s and dot(PQ, s) > 0: take the negative root this time, as the positive root is for a backwards travelling player (longer time; this is also the case presented in the diagram above).
Having the correct value for Δt from above will then enable us to find the intersection point o, and therefore the intended direction d:
Note that d is not normalized. Also, this solution works for 3D too, unlike an approach with angles.
Let subscript 1 mark the player, and subscript 2 mark the AI:
initial: position (x_i, y_i)
angle: alpha_i
speed: u_i
The positions as a function of time t are :
player: (x_1 + u_1 * t * cos(alpha_1), y_1 + u_1 * t * sin(alpha_1))
AI's bullet: (x_2 + u_2 * t * cos(alpha_2), y_2 + u_2 * t * sin(alpha_2))
You have 2 uknowns:
t - the time of collision
alpha_2 - the angle the AI should shoot
The collision happens when Xs and Ys match. i.e.:
x_1 + u_1 * t * cos(alpha_1) = x_2 + u_2 * t * cos(alpha_2)
y_1 + u_1 * t * sin(alpha_1) = y_2 + u_2 * t * sin(alpha_2)
So,
alpha_2 = arcos( (x_1 + u_1 * t * cos(alpha_1) - x_2) / u_2 * t )
and also
alpha_2 = arcsin( (y_1 + u_1 * t * sin(alpha_1) - y_2) / u_1 * t )
substitue your values and equate these to expressions of alpha_2 to obtain t, then you can substitue t in either expression to obtain the angle alpha_2.

Distance from point to ellipse

I need to somehow compute the distance between a point and an Ellipse.
I describe the Ellipse in my program as coordinates x = a cos phi and y = b sin phi (where a,b are constants and phi the changing angle).
I want to compute the shortest distance between a point P and my ellipse.
My thought were to calculate the vector from the center of my ellipse and the point P and then find the vector that start from the center and reaches the end of the ellipse in the direction of the point P and at the end subtract both vectors to have the distance (thi may not give the shortest distance but it's still fine for what I need.
The problem is I don't know how to compute the second vector.
Does someone has a better Idea or can tell me how I can find the second vetor?
Thanks in advance!
EDIT1:
ISSUE:COMPUTED ANGLE DOESN'T SEEM TO GIVE RIGHT POINT ON ELLIPSE
Following the suggestion of MARTIN R, I get this result:
The white part is created by the program of how he calculates the distance. I compute the angle phi using the vector from the center P (of ellipse) to the center of the body. But as I use the angle in the equation of my ellipse to get the point that should stay on the ellipse BUT also having same direction of first calculated vector (if we consider that point as a vector) it actually gives the "delayed" vector shown above.
What could be the problem? I cannot really understand this behavior (could it have something to do with atan2??)
EDIT2:
I show also that in the other half of the ellipse it gives this result:
So we can see that the only case where this works is when we have phi = -+pi/2 and phi = -+pi
IMPLEMENTATION FAILED
I tried using the implementation of MARTIN R but I still get the things wrong.
At first I thought it could be the center (that is not always the same) and I changed the implementation this way:
func pointOnEllipse(ellipse: Ellipse, p: CGPoint) -> CGPoint {
let maxIterations = 10
let eps = CGFloat(0.1/max(ellipse.a, ellipse.b))
// Intersection of straight line from origin to p with ellipse
// as the first approximation:
var phi = atan2(ellipse.a*p.y, ellipse.b*p.x)
// Newton iteration to find solution of
// f(θ) := (a^2 − b^2) cos(phi) sin(phi) − x a sin(phi) + y b cos(phi) = 0:
for _ in 0..<maxIterations {
// function value and derivative at phi:
let (c, s) = (cos(phi), sin(phi))
let f = (ellipse.a*ellipse.a - ellipse.b*ellipse.b)*c*s - p.x*ellipse.a*s + p.y*ellipse.b*c - ellipse.center.x*ellipse.a*s + ellipse.center.y*ellipse.b*c
//for the second derivative
let f1 = (ellipse.a*ellipse.a - ellipse.b*ellipse.b)*(c*c - s*s) - p.x*ellipse.a*c - p.y*ellipse.b*s - ellipse.center.x*ellipse.a*c - ellipse.center.y*ellipse.b*s
let delta = f/f1
phi = phi - delta
if abs(delta) < eps { break }
}
return CGPoint(x: (ellipse.a * cos(phi)) + ellipse.center.x, y: (ellipse.b * sin(phi)) + ellipse.center.y)
}
We can see what happens here:
This is pretty strange, all points stay in that "quadrant". But I also noticed when I move the green box far far away from the ellipse it seems to get the right vector for the distance.
What could it be?
END RESULT
Using updated version of MARTIN R (with 3 iterations)
x = a cos(phi), y = b sin (phi) is an ellipse with the center at
the origin, and the approach described in your question can be realized like this:
// Point on ellipse in the direction of `p`:
let phi = atan2(a*p.y, b*p.x)
let p2 = CGPoint(x: a * cos(phi), y: b * sin(phi))
// Vector from `p2` to `p`:
let v = CGVector(dx: p.x - p2.x, dy: p.y - p2.y)
// Length of `v`:
let distance = hypot(v.dx, v.dy)
You are right that this does not give the shortest distance
of the point to the ellipse. That would require to solve 4th degree
polynomial equations, see for example distance from given point to given ellipse or
Calculating Distance of a Point from an Ellipse Border.
Here is a possible implementation of the algorithm
described in http://wwwf.imperial.ac.uk/~rn/distance2ellipse.pdf:
// From http://wwwf.imperial.ac.uk/~rn/distance2ellipse.pdf .
func pointOnEllipse(center: CGPoint, a: CGFloat, b: CGFloat, closestTo p: CGPoint) -> CGPoint {
let maxIterations = 10
let eps = CGFloat(0.1/max(a, b))
let p1 = CGPoint(x: p.x - center.x, y: p.y - center.y)
// Intersection of straight line from origin to p with ellipse
// as the first approximation:
var phi = atan2(a * p1.y, b * p1.x)
// Newton iteration to find solution of
// f(θ) := (a^2 − b^2) cos(phi) sin(phi) − x a sin(phi) + y b cos(phi) = 0:
for i in 0..<maxIterations {
// function value and derivative at phi:
let (c, s) = (cos(phi), sin(phi))
let f = (a*a - b*b)*c*s - p1.x*a*s + p1.y*b*c
let f1 = (a*a - b*b)*(c*c - s*s) - p1.x*a*c - p1.y*b*s
let delta = f/f1
phi = phi - delta
print(i)
if abs(delta) < eps { break }
}
return CGPoint(x: center.x + a * cos(phi), y: center.y + b * sin(phi))
}
You may have to adjust the maximum iterations and epsilon
according to your needs, but those values worked well for me.
For points outside of the ellipse, at most 3 iterations were required
to find a good approximation of the solution.
Using that you would calculate the distance as
let p2 = pointOnEllipse(a: a, b: b, closestTo: p)
let v = CGVector(dx: p.x - p2.x, dy: p.y - p2.y)
let distance = hypot(v.dx, v.dy)
Create new coordinate system, which transforms ellipse into circle https://math.stackexchange.com/questions/79842/is-an-ellipse-a-circle-transformed-by-a-simple-formula, then find distance of point to circle, and convert distance
I wrote up an explanation using Latex so it could be more readable and just took some screen shots. The approach I am sharing is one using a Newton step based optimization approach to the problem.
Note that for situations where you have an ellipse with a smaller ratio between the major and minor axis lengths, you only need a couple iterations, at most, to get pretty good accuracy. For smaller ratios, you could even probably get away with just the initial guess's result, which is essentially what Martin R shows. But if your ellipses can be any shape, you may want to add in some code to improve the approximation.
You have the Ellipsis center of (a, b) and an arbitrary point of P(Px, Py). The equation of the line defined by these two points looks like this:
(Y - Py) / (b - Py) = (X - Px) / (a - Px)
The other form you have is an ellipse. You need to find out which are the (X, Y) points which are both on the ellipse and on the line between the center and the point. There will be two such points and you need to calculate both their distance from P and choose the smaller distance.

Trigonometry calculation

I assume this is would be a basic question however, my math skills are lacking.
I am working on an iphone game where people draw their own platform to bounce an egg up.
The game consists of a platform connecting 2 nodes each of these nodes has an x and y value this platform can be at any angle depending on how the user draws it, when something hits this platform I need it to hit off perpendicularly. I know how much total power I need, how would I break it down between X and Y. I drew a picture to better explain...
Here are two examples the info I have about the problem is the X & Y coordinate of the nodes, and the length of the dotted perpendicular line. What I need to find is the length of the X and Y lines and if the X is going in a positive or negative direction.
If you have two nodes, N1 and N2, and line length of L, then:
ndx = N1.x - N2.x
ndy = N1.y - N2.y
ndist = sqrt(ndx*ndx + ndy*ndy)
x = ndy * L / ndist
y = ndx * L / ndist
If your two points are A and B, and the length of your line is L, you first need to find the angle AB makes with respect to the x-axis:
theta = atan( (B.x - A.x) / (B.y - A.y) )
Armed with this, you can figure out x and y thusly:
x = L * cos( theta )
y = L * sin( theta )
The only edge case you will have to consider is for a horizontal line (in which case the computation will fail because of divide by zero when calculating theta). In the case of a horizontal line, x=0 and y=L.