kinect toolbox c# syntax - c#

I have been studying the algorithm used in kinect toolbox to compare vector sequences, but I am struggling to understand this piece of code:
public static float DistanceTo(this List<Vector2> path1, List<Vector2> path2)
{
return path1.Select((t, i) => (t - path2[i]).Length).Average();
}
as far as I understand this takes two sequences of 2d vectors and computes the distance between them by means of euclidean distance, that is, it calculates the length of the difference between vectors, I however had never seen the syntax inside the parenthesis, specially the =>.
Any insight would be much appreciated.

You can simply unroll this select statement.
path1.Select((t, i) => (t - path2[i]).Length) iterates over path1, for every element in it, it selects the Vector2 element and its index in the path1 list.
From that intermediate result it will do the difference between the two corresponding vectors at the same index (t - path2[i]), where - is a parameter overload for the vector substraction method. From that difference it will calculate the vector length which is basically just a squared(?) summation over its elements.
Average() in the end just takes the average over all the given vector differences.
This C# code is semantically the same:
float sum = 0.0f;
for(int i = 0; i < path1.Count; i++)
{
sum += (path1[i] - path[2]).Length;
}
return sum / (float)path1.Count;
Or even nicer as a LINQ zip expression:
path1.Zip(path2, (left, right) => (left-right).Length).Average();

Related

How to find closest point on multisegment line

I'm trying to find a solution for best performance.
I need to find closet point on multisegment line (List points) to given point.
My line have thousands of points and I need to check distance to this line few times per second. So solution need to be very fast.
Right now I have something like below. It works but it is going to be slow when line have 10000+ points.
Maybe someone have idea how to make it faster?
public static float GetSqrDistXZ(Vector3 a, Vector3 b)
{
Vector3 vector = new Vector3(a.x - b.x, 0, a.z - b.z);
return vector.sqrMagnitude;
}
public static Vector3 NearestPointOnFiniteLine(Vector3 start, Vector3 end, Vector3 pnt)
{
Vector3 line = (end - start);
float len = Mathf.Sqrt(line.sqrMagnitude);
line.Normalize();
Vector3 v = pnt - start;
float d = (v.x * line.x) + (v.z * line.z);
d = Mathf.Clamp(d, 0f, len);
return start + line * d;
}
int pointsCount = line.points3.Count - 1; // line - List<Vector3> points.
float[] distances = new float[pointsCount];
for (int i = 0; i < pointsCount+1; i++) {
if (i >= 1) {
distances [i - 1] = GetSqrDistXZ (point, NearestPointOnFiniteLine (line.points3 [i - 1], line.points3 [i], point));
}
}
int minListIndexLeft = System.Array.IndexOf (distances, Mathf.Min (distances));
float minimalDistance = distances[minListIndexLeft];
Vector3 closestPoint = NearestPointOnFiniteLine (line.points3[minListIndexLeft], line.points3[minListIndexLeft+1], point);
You'll want to think about space partitioning. In this example I'm going to assume a 2D space, but this works in 3D just as well. Also there are much better solutions like BSP trees and stuff, but we'll keep it simple here.
Imagine putting a grid over your 2D space. Every segment (distance between 2 points) of your line intersects with one or more cells of that grid. What you have to do is to store the intersecting segments for every cell. If your line does not change, you can do that in one single pass on startup, or even store that information statically in an Asset.
But once you have that information, all you have to do is calculate the cell that your point is inside and then only check the line segments that intersect with that specific cell or a number of direct neighbours (see below). This makes finding the closest point lightning fast in comparison.
If you play with this idea on a piece of paper you may come across cases where this solution does not yield the closest point, because it did not consider a neighboring cell that contained a closer point. The easiest way to solve this is the following approach:
1. Find cell C, which is the cell your point is in
2. Let cellRange = 0
3. Let point B be undefined
4. Find closest point P among all segments that intersect cell C and its neighboring cells of range cellRange*
5. If B is the same as newly found point P then P is the solution. You are done.
6. Increase cellRange by 1
7. Let B = P
8. Repeat from step 4
* "neighboring cells of range cellRange" means:
cellRange 0: only cell C, no neighbours
cellRange 1: cell C and direct neighbours
cellRange 2: cell C, direct neighbours and their direct neighbours
...
This solution basically checks if increasing the search range improves the solution. As soon as increasing the range did not improve the solution, you found the closest point.

using float + Lambda Expressions C#

var distances = new Dictionary<char, float>();
var nodes = new List<char>();
I have this line to find the smallest distance
nodes.Sort((x, y) => distances[x] - distances[y]);
When I use int it works well, but when I used float I got a message
cannot convert lambda expression to type
'System.Collections.Generic.IComparer' because it is not a
delegate type
Do you have an idea?
First off, your original program is a bad programming practice when the values are integers. It works for chars, but I would avoid this bad programming practice.
The delegate you pass to the sort function must have a number of properties; in particular it must return a negative int if x is smaller than y, a positive int if x is greater than y, and zero if they are equal. Your original lambda does not do that for integer values. (See if you can find two integers x and y such that x is smaller than y but x - y is positive.)
The delegate must also impose a total order. In a total order:
Transitivity must hold. If A == B and B == C then A must equal C. If A < B and B < C then A must be smaller than C. And so on.
It must be antisymmetric. That is, if A < B then B > A, and so on.
Subtraction does not meet these conditions in integers. The correct code is to actually write a comparison.
nodes.Sort((x, y) => x < y ? -1 : (x > y ? 1 : 0));
That then works well for chars and floats, provided there are no NaNs. If you have NaNs then you need to do extra work to impose a total order.
I would also point out that this ordinal comparison on chars is usually not the comparison you want. Sure, this will correctly note that e is smaller than z, but simple ordinal comparison also says that z is smaller than é, which is likely not what you want. Character ordering depends on culture; are you sure you want to order by the order that the Unicode committee just happened to impose?
For more on this topic see my series of articles; it begins here:
http://ericlippert.com/2011/01/20/bad-comparisons-part-one/
You can't convert your lambda expression into a Comparison<char> (which is what you want) because it returns a float - you've effectively got a Func<char, char, float> there, whereas Comparison<char> is closer to Func<char, char, int>.
The simplest approach is to use float.CompareTo:
nodes.Sort((x, y) => distances[x].CompareTo(distances[y]));
Or if you don't need to sort in-place, you could use LINQ:
var sorted = nodes.OrderBy(x => distances[x]);
Reformulate the lambda expression as follows.
nodes.Sort((x, y) =>
{
float Result = distances[x] - distances[y];
if ( Result > 0.0f )
return 1;
else if ( Result < 0.0f )
return -1;
else
return 0;
});

How do I calculate opposite of a vector, add some slack

How can i calulate a valid range (RED) for my object's (BLACK) traveling direction (GREEN). The green is a Vector2 where x and y range is -1 to 1.
What I'm trying to do here is to create rocket fuel burn effekt. So what i got is
rocket speed (float)
rocket direction (Vector2 x = [-1, 1], y = [-1, 1])
I may think that rocket speed does not matter as fuel burn effect (particle) is created on position with its own speed.
A cheap and cheerful trick with 2D vectors is to transpose the x and y, then flip the sign on one of them to get the perpendicular vector (pseudo code):
Vector2 perpendicular ( -original.y, original.x ) // Or original.y, -original.x
Then you could do something like:
direction + perpendicular * rand(-0.3 , 0.3)
Update: having realised the question asks for the opposite vector (too busy looking at the picture!) I figure I had better answer that too. Multiply 'direction' by -1 to get the opposite vector. So this:
perpendicular * rand(-0.3 , 0.3) - direction
should give you a random direction vector somewhere in your range (not normalised, but close enough for these purposes). Then you can multiply that result by a random number depending on how long you want the tail.
If to expend upon OlduwanSteve's answer, you can make is such that it's somewhat physically accurate.
You want to create several vectors that will represent the expulsion (the red lines).
First define the number of vectors you want to represent the expulsion with - lets mark it n.
You want to get a set of n numbers which sum up to Vx. These numbers will be the x components of the expulsion vectors. You can do this like so (semi-pseudo code):
SumX = Vx;
for (i = 0; i < n; i++)
{
Ax[i] = -rand(0..SumX); // Ax is the array of all expulsion vectors x components
SumX -= Ax[i];
}
Now you'll want to calculate Ay (the y components of the expulsion vectors). This is quite similar to calculating the, except that SumY = 0.
Here instead of splitting up SumY among n elements, you need to decide a maximal y component. Best way I can think of to select this is to define a maximal allowed angle for the expulsion vectors and define the maximal Vy using: maxVy = minVx*tan(maxAlpha).
Now you can get Ay using this (semi-pseudo code):
SumY = maxVy*2; // The actual range is (-maxVy, maxVy), but using (0, 2*maxVy) is simpler IMO
for (i = 0; i < n; i++)
{
Ay[i] = rand(0..SumY);
SumY -= Ay[i];
}
for (i = 0; i < n; i++)
{
Ay[i] -= maxVy; // Translate the range back to (-maxVy, maxVy) from (0, 2*maxVy)
}
Now you have arrays of both the x and y components of the expulsion vectors. Iterate over both arrays and pair up elements to create the vectors (you don't have to iterate both arrays in the same order).
Notes:
• I align the axes in my calculations such that X is parallel to the objects speed vector (the green line).
• The calculation for maxVy does NOT guarantee that a vector of angle maxAlpha will be produced, it only guarantees that no vector of larger angle will be.
• The lines Ay[i] = rand(0..SumY) and Ax[i] = -rand(0..SumX) may lead to vectors with components of size 0. This may lead to annoying scenarios, I'd recommend to handle away such cases (for instance "while rand returns zero, call it again").

Compute the local max/min for a given X Y series

I have an array consist of Point2D ( which has two members, x and y), e.g., Point2D[] points. You cna think of this array as a series of points on a X Y graph. The array is sorted in such a way that it is arranged from the smaller Point2D.X to the bigger Point2D.X
My question is simple: how do you find the points ( and the corresponding item index right before and after those points) that are the local maxima/minima? Recall that local max/min is defined mathematically as dy/dx=0. So my task is that I would need to find the those points where dy/dx=0.
Please note that the the extreme points may or may not located right inside the Point2D array, as the graph is a smooth curve, not an linearly-piece-wise polyline. An extreme point can be the middle point of two points inside the array. for instance.
Is there any existing libraries/ components that already do this in C#?
Here is my method:
public class Point2D
{
public double X;
public double Y;
}
public class PointWithIndex
{
// the extreme point where dy/dx=0
public Point2D ExtremePoints;
// the index of the array for the point that locates right before this ExtremePoints
public int PrevItemIndex;
}
public static List<PointWithIndex> FindLocalExtrema(List<Point2D> xyPoints)
{
// the algorithm to find the max/min points of xyPoints
}
I suggest running a loop 0 < i < n - 1, check if P[i - 1].Y < P[i].Y && P[i + 1].Y < P[i].Y, then P[i] is a max. do the same with min.
I'm not sure if this is what you are looking for: The Catmull-Rom Spline which you can easily compute using the XNA Framework (in C#) as shown here.
The idea is: you will generate -iteratively or recursively- points using Catmull-Rom until you hit your local maxima.

Is there any algorithm for calculating area of a shape given co-ordinates that define the shape?

So I have some function that receives N random 2D points.
Is there any algorithm to calculate area of the shape defined by the input points?
You want to calculate the area of a polygon?
(Taken from link, converted to C#)
class Point { double x, y; }
double PolygonArea(Point[] polygon)
{
int i,j;
double area = 0;
for (i=0; i < polygon.Length; i++) {
j = (i + 1) % polygon.Length;
area += polygon[i].x * polygon[j].y;
area -= polygon[i].y * polygon[j].x;
}
area /= 2;
return (area < 0 ? -area : area);
}
Defining the "area" of your collection of points may be hard, e.g. if you want to get the smallest region with straight line boundaries which enclose your set then I'm not sure how to proceed. Probably what you want to do is calculate the area of the convex hull of your set of points; this is a standard problem, a description of the problem with links to implementations of solutions is given by Steven Skiena at the Stony Brook Algorithms repository. From there one way to calculate the area (it seems to me to be the obvious way) would be to triangulate the region and calculate the area of each individual triangle.
You can use Timothy Chan's algorithm for finding convex hull in nlogh, where n is the number of points, h is the number of convex hull vertices. If you want an easy algorithm, go for Graham scan.
Also, if you know that your data is ordered like a simple chain, where the points don't cross each other, you can use Melkman's algorithm to compute convex hull in O(N).
Also, one more interesting property of convex hull is that, it has the minium perimeter.
Your problem does not directly imply that there's a ready-made polygon (which is assumed by this answer). I would recommend a triangulation such as a Delaunay Triangulation and then trivially compute the area of each triangle. OpenCV (I've used it with a large number of 2D points and it's very effective) and CGAL provide excellent implementations for determining the triangulation.
I found another function written in Java , so i traslated it to C#
public static double area(List<Double> lats,List<Double> lons)
{
double sum=0;
double prevcolat=0;
double prevaz=0;
double colat0=0;
double az0=0;
for (int i=0;i<lats.Count;i++)
{
double colat=2*Math.Atan2(Math.Sqrt(Math.Pow(Math.Sin(lats[i]*Math.PI/180/2), 2)+ Math.Cos(lats[i]*Math.PI/180)*Math.Pow(Math.Sin(lons[i]*Math.PI/180/2), 2)),
Math.Sqrt(1- Math.Pow(Math.Sin(lats[i]*Math.PI/180/2), 2)- Math.Cos(lats[i]*Math.PI/180)*Math.Pow(Math.Sin(lons[i]*Math.PI/180/2), 2)));
double az=0;
if (lats[i]>=90)
{
az=0;
}
else if (lats[i]<=-90)
{
az=Math.PI;
}
else
{
az=Math.Atan2(Math.Cos(lats[i]*Math.PI/180) * Math.Sin(lons[i]*Math.PI/180),Math.Sin(lats[i]*Math.PI/180))% (2*Math.PI);
}
if(i==0)
{
colat0=colat;
az0=az;
}
if(i>0 && i<lats.Count)
{
sum=sum+(1-Math.Cos(prevcolat + (colat-prevcolat)/2))*Math.PI*((Math.Abs(az-prevaz)/Math.PI)-2*Math.Ceiling(((Math.Abs(az-prevaz)/Math.PI)-1)/2))* Math.Sign(az-prevaz);
}
prevcolat=colat;
prevaz=az;
}
sum=sum+(1-Math.Cos(prevcolat + (colat0-prevcolat)/2))*(az0-prevaz);
return 5.10072E14* Math.Min(Math.Abs(sum)/4/Math.PI,1-Math.Abs(sum)/4/Math.PI);
}

Categories