Skip to content

Instantly share code, notes, and snippets.

@adrianseeley
Created May 3, 2015 13:22
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save adrianseeley/264417d295ccd006e7fd to your computer and use it in GitHub Desktop.
Save adrianseeley/264417d295ccd006e7fd to your computer and use it in GitHub Desktop.
Largest-Triangle-Three Bucket Downsampling Graphs in C# (For an Array of Floats) http://i.imgur.com/UwhvV45.png
public float[] Downsample(float[] array, int Length)
{
int insert = 0;
float[] window = new float[Length];
float[] window_x = new float[Length];
int bucket_size_less_start_and_end = Length - 2;
float bucket_size = (float)(array.Length - 2) / bucket_size_less_start_and_end;
int a = 0;
int next_a = 0;
int max_area_point_x = 0;
float max_area_point_y = 0f;
window[insert] = array[a]; // Always add the first point
window_x[insert] = 0;
insert++;
for (int i = 0; i < bucket_size_less_start_and_end; i++)
{
// Calculate point average for next bucket (containing c)
float avg_x = 0;
float avg_y = 0;
int start = (int)(Math.Floor((i + 1) * bucket_size) + 1);
int end = (int)(Math.Floor((i + 2) * bucket_size) + 1);
if (end >= array.Length)
{
end = array.Length;
}
int span = end - start;
for (; start < end; start++)
{
avg_x += start;
avg_y += array[start];
}
avg_x /= span;
avg_y /= span;
// Get the range for this bucket
int bucket_start = (int)(Math.Floor((i + 0) * bucket_size) + 1);
int bucket_end = (int)(Math.Floor((i + 1) * bucket_size) + 1);
// Point a
float a_x = a;
float a_y = array[a];
float max_area = -1;
for (; bucket_start < bucket_end; bucket_start++)
{
// Calculate triangle area over three buckets
float area = Math.Abs((a_x - avg_x) * (array[bucket_start] - a_y) - (a_x - (float)bucket_start) * (avg_y - a_y)) * 0.5f;
if (area > max_area)
{
max_area = area;
max_area_point_x = bucket_start;
max_area_point_y = array[bucket_start];
next_a = bucket_start; // Next a is this b
}
}
// Pick this point from the Bucket
window[insert] = max_area_point_y;
window_x[insert] = max_area_point_x;
insert++;
// Current a becomes the next_a (chosen b)
a = next_a;
}
window[insert] = array[array.Length - 1]; // Always add last
window_x[insert] = array.Length;
return window;
}
@antontroskie
Copy link

Pretty good stuff!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment