Interpolating Z values when given complete and incomplete XYZ pairs - c#

I am building a windows form application that works with PolyLineZ (ESRI Shapefile) data and rewrites outlying Z values. The minimum and maximum Z-values are defined by the user through the interface
Let's take the following as an example, let's say the minimum is 0 and the maximum is 10:
XY Z
1,1 0
1,3 1
1,5 7
1,7 11*
1,10 10
The value with the 11 would need to be interpolated as it does not fall into the range defined by the user. This is a very simplified example obviously. Some PolyLines can be missing more values.
What I've done:
I've researched linear interpolation. Looked at example youtube videos, having a hard time wrapping my head around it.
What I need:
Code examples from either any language or an "English" explanation of the theory behind linear/bilinear/trilinear interpolation so that I can implement it into my program. My math skills aren't the greatest, so I have a hard time understanding wikipedias definition of it.
I'm also assuming that linear interpolation is what I need to research,
EDIT: Currently implementing the following, stop me if I'm wrong
I'm using what I think is Pythagorean Theory type approach. I haven't made it catch exceptions yet (ie, making sure the left point is actually left, make sure the list doesn't run out of bounds, etc), that can come later
internal static double calculateDistance(XYPoints a, XYPoints b)
{
double xd = b.X - a.X;
double yd = b.Y - a.Y;
return Math.Sqrt(xd * xd + yd * yd);
}
for (var i = 0; i < polylinez.ZPoints.Count;i++)
{
if (polylinez.ZPoints[i] > maxValue || (polylinez.ZPoints[i] < minValue))
{
//polylinez.ZPoints[i] = (((1 - polylinez.XYpoints[i].X) * polylinez.ZPoints[i - 1]) + (polylinez.XYpoints[i].X * polylinez.ZPoints[i + 1]));
double prevdistance = calculateDistance(polylinez.XYpoints[i - 1], polylinez.XYpoints[i]);
double nextdistance = calculateDistance(polylinez.XYpoints[i], polylinez.XYpoints[i + 1]);
double fraction = prevdistance / nextdistance;
double diffsBetweensZ = polylinez.ZPoints[i + 1] - polylinez.ZPoints[i - 1];
Console.WriteLine(polylinez.ZPoints[i - 1] + (diffsBetweensZ * fraction));
}
}
return polylinez;
It returns 9.12 as an answer for the above example table. This sounds about right to me. I checked my distance calculator method with sample data on the internet, and it seems to be doing the trick.

First step, create a routine for calculating distances:
internal static double calculateDistance(XYPoints a, XYPoints b)
{
double xd = b.X - a.X;
double yd = b.Y - a.Y;
return Math.Sqrt(xd * xd + yd * yd);
}
I changed the variable names to something more logical (my variable names were different)
//get distance frpm previous point to point in question
double prevdistance = calculateDistance(prevXYpoint, currentXYPoint);
//get distance frpm point in question to the next point
double nextdistance = calculateDistance(currentXYPoint, nextXYPoint);
//generate a ratio
double fraction = prevdistance / (nextdistance + prevdistance);
//find out the difference between the two known points
double diffsBetweensZ = nextZpointValue - prevZpointValue;
//interpolate!
double newZvalue = (prevZpointValue + (diffsBetweensZ * fraction));
I checked this on several sets of data and it's the most accurate thing I can find... what blows my mind is that I couldn't find any existing code anywhere to do this.

Related

Get the inverse of a function, millibels to percentage & percentage to millibels

Audio noob here and math challenged. I'm working with DirectSound which uses a -10000 to 0 range, converting that to a 0-100 scale.
I found this function here to obtain the millibels based on a percentage:
private int ConvertPercentageToMillibels(double value)
{
double attenuation = 1.0 / 1024.0 + value / 100.0 * 1023.0 / 1024.0;
double db = 10 * Math.Log10(attenuation) / Math.Log10(2);
return (int)(db * 100);
}
I need help getting the inverse of this function, basically to get the percentage based on millibels. Here is what I've got so far, which isn't working:
private double ConvertMillibelsToPercentage(int value)
{
double db = value / 100;
double attenuation = Math.Pow(10, db) / 10 * Math.Pow(10, 2);
double percentage = (1.0 * attenuation) - (1024.0 * 100.0 / 1023.0 * 1024.0);
return percentage;
}
Here you go!
private double ConvertMillibelsToPercentage(int value)
{
double exponent = ((value / 1000.0) + 10);
double numerator = 100.0 * (Math.Pow(2, exponent) - 1);
return numerator / 1023.0;
}
Answer will differ slightly due to obvious issues that arise from going between an int and a double.
EDIT: Per the teach how to fish request, here are the first mathematical steps toward arriving at the solution. I didn't show the whole thing because I didn't want to spoil allll the fun. All log functions should be considered Log base 10 unless otherwise noted:
millibels = db*100; // Beginning to work backward
millibels = 10*Log(attenuation)*(1/Log(2))*1000; // Substituting for db
millibels = 1000*Log(attenuation)/Log(2); // Simplifying
let millibels = m. Then:
m = 1000*Log(attenuation)/Log(2);
from here you can go two routes, you can either use properties of logs to find that:
m = 1000* Log_2(attenuation);// That is, log base 2 here
attenuation = 2^(m/1000);
OR you can ignore that particular property and realize:
attenuation = 10^(m*Log(2)/1000);
Try to work it out from one of the above options by plugging in the value that you know for attenuation:
attenuation = (1/1024)+(percentage/100)*(1023/1024);
And then solving for percentage. Good luck!
PS If you ever get stuck on things like this, I highly recommend going to the math stack exchange - there are some smart people there who love to solve math problems.
OR if you are particularly lazy and just want the answer, you can often simply type this stuff into Wolfram Alpha and it will "magically" give you the answer. Check this out

Time to Temperature Calculation

This might not be the correct place for this, so apologies in advance if it isn't.
My situation - I need to come up with a simple formula/method of giving it an hour E.g. 13, 15, 01 etc, and based on that number, the method will return the 'approx' temperature for that particular time.
This is very approximate and it will not use weather data or anything like that, it will just take the hour of the day and return a value between say -6 deg C > 35 deg C. (very extreme weather, but you get the idea.)
This is the sort of examples I would like to know how to do:
Just as a note, I COULD use an ugly array of 24 items, each referencing the temp for that hour, but this needs to be float based - e.g. 19.76 should return 9.25 deg...
Another note: I don't want a complete solution - I'm a confident programmer in various languages, but the maths have really stumped me on this. I've tried various methods on paper using TimeToPeak (the peak hour being 1pm or around there) but to no avail. Any help would be appreciated at this point.
EDIT
Following your comment, here is a function that provides a sinusoidal distribution with various useful optional parameters.
private static double SinDistribution(
double value,
double lowToHighMeanPoint = 0.0,
double length = 10.0,
double low = -1.0,
double high = 1.0)
{
var amplitude = (high - low) / 2;
var mean = low + amplitude;
return mean + (amplitude * Math.Sin(
(((value - lowToHighMeanPoint) % length) / length) * 2 * Math.PI));
}
You could use it like this, to get the results you desired.
for (double i = 0.0; i < 24.0; i++)
{
Console.WriteLine("{0}: {1}", i, SinDistribution(i, 6.5, 24.0, -6.0, 35.0));
}
This obviously discounts environmental factors and assumes the day is an equinox but I think it answers the question.
So,
double EstimatedTemperature(double hour, double[] distribution)
{
var low = Math.Floor(hour);
var lowIndex = (int)low;
var highIndex = (int)Math.Ceiling(hour);
if (highIndex > distribution.Count - 1)
{
highIndex = 0;
}
if (lowIndex < 0)
{
lowIndex = distribution.Count - 1;
}
var lowValue = distribution.ElementAt(lowIndex);
var highValue = distribution.ElementAt(highIndex);
return lowValue + ((hour - low) * (highValue - lowValue));
}
assuming a rather simplistic linear transition between each point in the distibution. You'll get erroneous results if the hour is mapped to elements that are not present in the distribution.
For arbitrary data points, I would go with one of the other linear interpolation solutions that have been provided.
However, this particular set of data is generated by a triangle wave:
temp = 45*Math.Abs(2*((t-1)/24-Math.Floor((t-1)/24+.5)))-10;
The data in your table is linear up and down from a peak at hour 13 and a minimum at hour 1. If that is the type of model that you want then this is really easy to put into a formulaic solution. You would just simply perform linear interpolation between the two extremes of the temperature based upon the hour value. You would have two data points:
(xmin, ymin) as (hour-min, temp-min)
(xmax, ymax) as (hour-max, temp-max)
You would have two equations of the form:
The two equations would use the (x0, y0) and (x1, y1) values as the above two data points but apply them the opposite assignment (ie peak would be (x0, y0) on one and (x1, y1) in the other equation.
You would then select which equation to use based upon the hour value, insert the X value as the hour and compute as Y for the temperature value.
You will want to offset the X values used in the equations so that you take care of the offset between when Hour 0 and where the minimum temperature peak happens.
Here is an example of how you could do this using a simple set of values in the function, if you wish, add these as parameters;
public double GetTemp(double hour)
{
int min = 1;
int max = min + 12;
double lowest = -10;
double highest = 35;
double change = 3.75;
return (hour > max) ? ((max - hour) * change) + highest : (hour < min) ? ((min - hour)*change) + lowest : ((hour - max) * change) + highest;
}
I have tested this according to your example and it is working with 19.75 = 9.6875.
There is no check to see whether the value entered is within 0-24, but that you can probably manage yourself :)
You can use simple 2 point linear approximation. Try somthing like this:
function double hourTemp(double hour)
{
idx1 = round(hour);
idx2 = idx1 + 1;
return (data[idx2] - data[idx1]) * (hour - idx1) + data[idx1];
}
Or use 3,5 or more points to get polynom cofficients with Ordinary Least Squares method.
Your sample data similar to the sin function so you can make sin function approximation.

get match percentages between two objects by parameters

I want to create a program that will automate a process that i am doing manually today.
I apologize if the solution seems to be easy i just don't want to think about new algorithm specially for my problem because i am sure that someone already thought about it.
My Scenario is this:
I have candidates list that are looking for jobs and I have jobs list.
For each candidate I know the following requirements of the job that he is searching for. like:
Salary
Location of the Job
Company Size (Big / Small)
In the manual process what i do is to match between those candidate's requirements parameters to the job's requirements parameter and "return" the jobs that seems to fit to the candidate (it doesn't have to be a completely match).
Of course i am considering candidate's requirement is "nice to have" or "must have".
I am searching for an algorithm that returns a fit percentage between each candidate to each job.
Can someone please point me to a any name of matching algorithm like this.
Thanks
My advice is to convert every object to a vector in a 3-D space and then find the Euclidean distance between the two vectors (objects).
First, assign salary, location and size to x, y and z axis, respectively.
Then map the properties to [0, 1] interval of the axis.
For example, if your min salary is 1'000, and max salary is 10'000, then you would map:
$ 1'000 -> 0 on the x axis,
$ 10'000 -> to 1 on the x axis.
Mapping locations is hard, but let's say you have a map grid, and you assign a value to each patch of the grid according to geo position - closer ones have similar values. For example, US states provide us with a good example:
New York -> 1.0 on the y axis,
New Jersey -> 0.99 on the y axis,
...
California -> 0.1 on the y axis.
Map company sizes something like:
start-up -> 0.2 on the z axis,
...
multinational -> 1.0 on the z axis.
So, to give an example: John wants a salary of 9.000, wants a job in New York, and wants to work in a start-up company. His vector in 3D space would be [0.82, 1.00, 0.1].
Peter wants a salary of 5.500, wants a job in New Jersey, and wants to work in a really big company - [0.5, 0.99, 0.8]. And at last, Mike wants a salary of 8.000, a job in California, and a start-up too - [0.73, 0.1, 0.1].
According to formula for Euclidean distance in 3D space:
d(a, b) = sqrt((a1-b1)^2 + (a2-b2)^2 + (a3 - b3)^2)
Distance between John and Peter is: d(J, P) = 0.77
Distance between John and Mike is: d(J, M) = 0.90
So the conclusion would be that John and Peter are closer than John and Mike.
One more thing you could do is to bring in some constants to each axis to emphasize the importance of it (location is more important than company size, for example) so in the formula you could do something like:
d(a, b) = sqrt((a1-b1)^2 + (C*a2 - C*b2)^2 + (a3 - b3)^2), where C = 10
similiarity(A,B) = 1 / (1 + (distance(A,B) / unit))
Case where distance is 0:
similarity(A,A)
= 1 / (1 + (distance(A,A) / unit))
= 1 / (1 + (0 / unit))
= 1 / (1 + 0)
= 1.0
~ 100 %
Case where distance is infinite:
similarity(A,Z)
= 1 / (1 + (distance(A,Z) / unit))
= 1 / (1 + (infinity / unit))
= 1 / infinity
= 0.0
~ 0 %
Code:
JobComparison* compare (Job a, Job b)
{
// define units based on measurement
double unit1 = 1000.0;
double unit2 = 100.0;
double unit3 = 10.0;
// calculate distance
double d1 = abs(a.salary - b.salary);
double d2 = distance(a.location, b.location);
double d3 = abs(a.companySize - b.companySize);
// calculate similiarity
double p1 = 1 / (1 + (d1 / unit1));
double p2 = 1 / (1 + (d2 / unit2));
double p3 = 1 / (1 + (d3 / unit3));
return new JobCompare(p1, p2, p3);
}
public class JobCompare
{
public:
double salarySimiliarity;
double locationSimiliarity;
double companySimiliarity;
}
public class Job
{
public:
double salary;
Location location;
double companySize;
}

Find closest city to given location

I am trying to find the closest city to given location. I have stored location of some cities that I want to work with. And I have my location, but I dont know how to find the closest city to my location ?
Cities
New York - Lat 40.714353; Long -74.005973
Washington - Lat 38.895112; Long -77.036366
....more cities
My location
Philadephia - Lat 39.952335; Long -75.163789
So how should I compare the coords to find the closest city ? I am doing program in C# but just knowing the solution of algorythm is enaught for me :)
Thanks for any help
You should use your high school knowledge to solve this problem, your alghorithm is:
closest = sqrt ( (lat2 - lat1) ^2 + (Long2-Long1) ^2 )
now this give you your air distance.
so, when you do this for an array of values, you can use asort function to compare which one is closest to you.
Strictly, you'd want to use the Haversine formula.
However, while you could perhaps be just slightly out in far northern or far southern points, you could probably get by by pretending that Mercator projections are accurate for distance, and ignoring the curvature of the earth. This is especially true if you are going to have lots of cities, as the error is greater, the further points are from the target point. Hence you would just use Pythagoras':
relDist = √((xLat - yLat) × (xLat - yLat) + (xLng - yLng) × (xLng - yLng))
But since you only care about (and only get) a relative ordering, you can skip the square-root bit, which is the heaviest step:
relDist = (xLat - yLat) × (xLat - yLat) + (xLng - yLng) × (xLng - yLng)
As well as being faster in and of itself, it can also be reasonably preformed on integers, should you store your coordinates as multiples of the actual coordinate (e.g. storing New York's (40.664167, -73.938611) as the pair (406642, -739386). This can be a big boost if you want to quickly sort a large number of places in order of proximity to a given point.
If however you really care about precision in the face of the fact that the earth is round, then the following implements Haversine:
private const double radiusE = 6378135; // Equatorial radius
private const double radiusP = 6356750; // Polar radius
private const double radianConv = 180 / Math.PI;
public static double GetDistanceBetweenPoints(double lat1, double long1, double lat2, double long2)
{
double dLat = (lat2 - lat1) / radianConv;
double dLong = (long2 - long1) / radianConv;
double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(lat2) * Math.Sin(dLong/2) * Math.Sin(dLong/2);
return Math.Sqrt((Math.Pow(radiusE * radiusP * Math.Cos(lat1 / radianConv), 2)) / (Math.Pow(radiusE * Math.Cos(lat1 / radianConv), 2) + Math.Pow(radiusP * Math.Sin(lat1 / radianConv), 2))) * (2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)));
}
The distance bitween two points (x1, y1) and (x2, y2) is
d = sqrt((x1 - x2) ^ 2 + (y1 - y2) ^ 2)
so in c# you we will have:
public City FindNearestCity(double currentLatitude, double currentLogitude, List<City> cities)
{
Dictionary<City, double> distances = new Dictionary<City, double>();
foreach (City city in cities)
{
double distance = Math.Sqrt(Math.Pow(city.latitude - currentLatitude, 2) + Math.Pow(city.Longitude - currentLogitude, 2));
distances.Add(city, distance);
}
double minimumDistance = distances.Min(distance => distance.Value);
return distances.First(distance => distance.Value == minimumDistance).Key;
}
Visit here
you can find two c# function using Brute force and divide-and-conquer algorithms to find the closest two points among a set of given points in two dimensions.
Jon's answer is very inspiring, although there're few missing pieces.
lat1 should be in a
double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(lat1/ RadianConv) * Math.Cos(lat2/ RadianConv) * Math.Sin(dLong / 2) * Math.Sin(dLong / 2);
The simulated radius in last statement gave 2000ish sometimes, which should be close to either RadiusE or RadiusP, so I used mean radius instead.
return 6371* (2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)));

How to find the surrounding area 25 miles using latitude & longitude from the current user location

I found Haversine Formula in C# is there any other method better than this.
public double HaversineDistance(LatLng pos1, LatLng pos2, DistanceUnit unit)
{
double R = (unit == DistanceUnit.Miles) ? 3960 : 6371;
var lat = (pos2.Latitude - pos1.Latitude).ToRadians();
var lng = (pos2.Longitude - pos1.Longitude).ToRadians();
var h1 = Math.Sin(lat / 2) * Math.Sin(lat / 2) +
Math.Cos(pos1.Latitude.ToRadians()) * Math.Cos(pos2.Latitude.ToRadians()) *
Math.Sin(lng / 2) * Math.Sin(lng / 2);
var h2 = 2 * Math.Asin(Math.Min(1, Math.Sqrt(h1)));
return R * h2;
}
I suppose it is a matter of what you want to do with it. My guess is that you are trying to calculate distance based on a ZIP (Post) code and you want to know if pos2 is within x distance of pos1.
What you first need to understand is that (unless you have some awesome Geo Spatial data to work with) all calculations do not generally take into account elevation or any other topographical attributes of the given area so your calculations won't be exact. Further these calculations are "as the crow flies" which means point x to point y is a straight line so while point y may lie within 25 miles of central point x it may actually be 30 miles to travel from central point x to point y.
That being said the Haversine Formula is your best bet unless you are calculating small distances (< ~12 miles) in which case you could use Pythagorean's theorem which is expressed as:
d = sqrt((X2 - X1)^2 + (Y2 - Y1)^2)
Where X and Y are your coordinates, obviously. This is much faster but is far less accurate especially as distance increases.
The Haversine Formula is slow especially if you are repeated calling it but I am unaware of any faster methods for calculating distance based on this formula.

Categories