Shortest distance from a point to this curve - c#

I need to find the distance of multiple points to a curve of the form: f(x) = a^(k^(bx))
My first option was using its derivative, using a line of the form with the inverse of the derivative, giving it coordinates of the Point and intersecting it with the original curve. Finally, we calculate the distance between points with simple geometry.
That's the mathematical process that I usually follow. I need to save time (since I'm doing a genetic algorithms program) so I need an efficient way to do this. Ideas?

The distance between a point (c,d) and your curve is the minimum of the function
sqrt((c-x)^2 + (d-a^(k^(bx)))^2)
To find its minimum, we can forget about the sqrt and look at the first derivative. Find out where it's 0 (it has to be the minimal distance, as there's no maximum distance). That gives you the x coordinate of the nearest point on the curve. To get the distance you need to calculate the y coordinate, and then calculate the distance to the point (you can just calculate the distance function at that x, it's the same thing).
Repeat for each of your points.
The first derivative of the distance function, is, unfortunately, a kind of bitch. Using Wolfram's derivator, the result is hopefully (if I haven't made any copying errors):
dist(x)/dx = 2(b * lna * lnk * k^(bx) * a^(k^(bx)) * (a^(k^(bx)) - d) - c + x)

To find distance from point to curve it's not a simple task, for that you need to find the global of function where f(x) is the function which determine your curve.
For that goal you could use:
Simplex method
Nelder_Mead_method
gradient_descent
This methods implemented in many libraries like Solver Foundation, NMath etc.

Related

Check if the mouse is over a Bézier curve [duplicate]

This question already has answers here:
Closest point on a cubic Bezier curve?
(6 answers)
Closed 4 years ago.
My approach was to loop trough the curve and check the mouse distance to various points
But the points get closer together as the curve get steeper, and if the mouse distance threshold is too high it prioritizes the first point in the loop instead of the closet to the mouse.
is there a way to get uniform points in it? Or to check if the mouse is over the Bézier curve and get the position in the curve?
I do it like this:
subdivide you curve to few chunks
tne number of chunks depends on the order of curve. As I usually use cubics I empirically find out that ~8 chunks is enough (for my purposes).
compute the closest point to a chunk
So simply handle each chunk as line and compute closest point on the line to the mouse position (minimal perpendicular distance). By computing it for each chunk and remember the closest one.
Now after this we know which chunk contain the "closest" point so from the intersection between line and perpendicular line to it going through mouse position from previous step we should have a parameter u=<0,1> telling us where on the chunk line the closest point is and we also know the curve parameter t of both endpoints of the chunk line (t0,t1). From this we can approximate t for the closest point simply by doing this:
t = t0 + (t1-t0)*u
On the image t0=0.25 and t1=0.375. This is sometimes enough but if you want better solution so after this just set:
dt = (t1-t0)/4
t0 = t-dt
t1 = t+dt
Use the t0,t,t1 to compute 3 endpoints of 2 chunks and look for the closest point again. You can recursively do this few times as with each iteration you increase precision of the result
The perpendicular distance of point to a line is computed by computing intersection between the line and axis perpendicular to it going through the point in question. So if the line is defined by endpoints p0,p1 and the queried point (mouse) is q then the axis in 2D will be:
dp=p1-p0 // line direction
dq=(dp.y,-dp.x) // axis direction is perpendicular to dp
dq/= |dq| // normalize
p(u) = p0+dp*u // point on line
p(v) = q +dq*v // point on axis
u = <0,1> // parameter on line
v = <-inf,+inf> // parameter on axis
And we want to know u,v from
p0+dp*u = q +dq*v
which is system of 2 linear equations in 2D. In 3D you need to exploit cross product to obtain the dq and the system would contain 3 equations. Solving this sytem will give you u,v where u will tell you where in the chunk the closest point is and |v| is the perpendicular distance itself. Do not forget that if u is not in the range <0,1> then you have to use closer endpoint of the line as the closest point.
The system can be solved either algebraically (but beware the edge cases as there are 2 solutions for the equations in 2D) or use inverse matrix...
There are two main approaches - subdivision of curve into small line segments and analytical solution.
For the second case you have to build polynomial for squared distance from point to curve depending on parameter t, differentiate it, and find zeros of result (5-th order polynomial). Then choose minimum from distances to point at t[i], t=0, t=1.
Another point of view - get projection of point onto curve, so curve tangent in this point is perpendicular to vector point-curvepoint, it should give the same expression.
About uniform points - it is rather hard problem because curve length could not be calculated analytically. But subdivision gives quite good approximation.

How to sort an array of coordinates according to proximity of a specific coordinate

I have an array of random coordinates (latitude and longitude) and I would like to sort by distance according to a specific coordinate. Can anyone help me ? I have searched on internet but I wasn't able to find it. thanks in advance.
I am using the code below but is not efficient because I need to get each one coordinate by from the nearest to the farest :
var mapItens = ((from i in coordinatesArray
(latitudeCurrent > i.Latitude && ((latitudeCurrent - i.Latitude) < 0.700 || (longitudeCurrent - i.Longitude) < 0.700)) ||
(latitudeCurrent < i.Latitude && ((i.Latitude - latitudeCurrent) < 0.700 || (i.Longitude - longitudeCurrent) < 0.700)))
select i).toList();
You need to sort your points according to their distance from the point of interest. (Let's call it 'point i'.)
That would involve invoking the IList.Sort() function and passing it an IComparer. (See https://msdn.microsoft.com/en-us/library/234b841s(v=vs.110).aspx) The comparer is given two points, a and b, and is supposed to determine which one is "larger".
According to the definition of your problem, point a is larger than point b if the distance between a and i is larger than the distance between b and i. So, your comparer simply calculates these two distances, and compares the distances instead of the points.
If your coordinates span over such a large geographic area that the curvature of Earth matters, then you need special a formula to calculate the distance between two points given in geographic coordinates. That's not trivial, and people generally use libraries to do that kind of thing.
If the coordinates are confined within a small enough geographic area that the curvature of the Earth does not matter, then you can use a simple trigonometric distance formula:
distance = square-root-of( (a.x - i.x)2 + (b.y - i.y)2 ).
And since you don't actually care about exact distances, but only about how the distances compare against each other, you can use a hacky little trick and avoid taking the square root, the comparison will still yield the same result.

How to simulate pendulum movement with high amplitude in C#

I need to make a C# simulator for a simple pendulum.
I have been searching the web for 3 days and I am stuck.
The problem is I have found many equations that would give the angle position as a function of time, which is perfect for my needs for making a visual simulation but the problem is those functions only works for angles smaller than 10, but I should be able to simulate from any angle.
Example of a equation that only works for small angles:
Source: http://hyperphysics.phy-astr.gsu.edu/hbase/pend.html#c2
And the equations that should work for any angle (Amplitude) are too complicated as it involves differential equations, and derivatives. I don't know how to implement these in C#.
Example of a equation that I think would work but I don't know how to use:
Source: http://www.sbfisica.org.br/rbef/pdf/070707.pdf
(Equation number 32)
the problem of this last equation is the "sn" that is Jacobi elliptic function sn(u;m) u, and I don't know how to use in C#
Can someone help? maybe with another equation that I could use programmatically, or helping me understand how I could use this last one if it would really works.
If you want to simulate the pendulum, you don't need the exact solution. The only you need is a sufficiently good approximation at every step of your simulation, combined with sufficient steps. This is similar to approximating a circle with a sufficiently large number of segments, each of them, tangent to the ideal circle.
Now, consider your pendulum has a deviation of theta degrees (or radians) from the vertical as depicted below:
The mass m will have a weight of m * g, where g is the gravity acceleration. Now, let's approximate the angle alpha where the pendulum will move in the next dt seconds (dt is the duration of one step, so dt is just a fraction of a second).
Since the acceleration on the tangent direction is g * cos(theta) we can approximate the tangent distance the pendulum would travel in dt seconds as if the acceleration were constant during this lapse:
d = v * dt + g * sin(theta) (dt)^2 / 2
where v is the tangential speed of the pendulum at the angular position theta. Now we can calculate alpha as
alpha = arcsin(d / r)
where r is the radius. Thus, the only that remains is to update the value of v so we can repeat the same in the next step. Here is how
v := v + g * sin(theta) * dt
Of course, when the pendulum starts you can initialize v = 0.
I haven't tried this myself, so please, let me know if this "simulated" approach worked for you. Good luck!

Nearest plane to non-coplanar points?

I have a number of non-coplanar 3D points and I want to calculate the nearest plane to them (They will always form a rough plane but with some small level of variation). This can be done by solving simultaneous linear equations, one for each point, of the form:
"Ax + By + Cz + D = 0"
The problem I'm having at the moment is twofold.
Firstly since the points are 3D floats they can't be relied on to be precise due to rounding errors.
Secondly all of the methods to solving linear equations programatically that I have found thus far involve using NXN matrices which severely limits what I would be able to do given that I have 4 unknowns and any number of linear equations (due to the variation in the number of 3D points).
Does anyone have a decent way to either solve the simultaneous linear equations without these constraints or, alternatively, a better way to calculate the nearest plane to non-coplanar points? (The precision of the plane calculation is not too much of a concern)
Thanks! :)
If your points are all close to the plane, you have a choice between ordinary least squares (where you see Z as a function of two independent variables X and Y and you minimize the sum of squared vertical distances to the plane), or total least squares (all variables independent, minimize the sum of normal distances). The latter requires a 3x3 SVD. (See http://en.wikipedia.org/wiki/Total_least_squares, unfortunately not the easiest presentation.)
If some of the points are outliers, you will need to resort to robust fitting methods. One of them is RANSAC: choose three points are random, build their plane and compute the sum of distances of all points to the plane, as a measure of fitness. Keep the best result after N drawings.
There are numerical methods for linear regression, which calculates the nearest line y=mx+c to a set of points. Your solution will be similar, only it has one more dimension and is thus a "planar regression".
If you don't care the mathematical accuracy of the algorithm and just want to get a rough result, then perhaps you'd randomly 3 points to construct a plane vector, then adjust it incrementally as you go through the rest of the points. Just some thoughts...

slight changes in long lat for varations of point with the same location

Bit of a weird one this. I'm rendering datasets on a map and need to split out points that have exactly the same long and lat. I had the idea of grouping my dataset by long and lat and where they are the same adjusting slightly so that they are visible as seperate entities on the map - rather than overlapping.
I'm using linq to group them and then enumerating my grouped items and I'd like to spiral the adjusted points around the orginal point (this is a requirement as I may have a few hundred points that are the same geographically) so that they spread out from the original point.
Does anyone know of a simple calculation i can add to my loop to adjust the items in this manner.
Thanks,
The math behind this is pretty simple. A circle can be represented by the sine function in the x-axis and the cosine function in the y-axis. Here's some pseudo-code:
int num = OverlappingPoints.Length;
for(int i = 0; i < num; ++i)
{
int radius = 50;
// using 2*pi because most math functions use radians... change 2*pi to 360 if your math library uses 360 degrees instead of 2*pi radians to represent a circle.
Map.Plot(OverlappingPoints[i].Latitude + radius*sin(2*pi*i/num),
OverlappingPoints[i].Latitude + radius*cos(2*pi*i/num));
}
That pseudo-code, if properly implemented, will draw the points out in a circle around the original point. Change the radius multiplier to the sine and cosine functions if you want to increase the radius of the circle. If you want the points to spiral out instead of making a circle, choose a number of points per circle revolution and replace num with that number in the sin/cos functions. Also, increase the radius after each loop iteration, probably by using a number and multiplying it by the loop index. (i.e. you could change radius to 50*i).
Hope this helps.

Categories

Resources