Fixed bug determing the closest keyframe point to another point. Added additional unit tests. Added new method to get the # of Points in a keyframe.

This commit is contained in:
Jonathan Thomas
2015-02-22 01:04:54 -06:00
parent b976b8220b
commit 61ed19250e
6 changed files with 54 additions and 13 deletions

View File

@@ -137,6 +137,9 @@ namespace openshot {
// Get the number of values (i.e. coordinates on the X axis)
int GetLength();
/// Get the number of points (i.e. # of points)
int GetCount();
/// Get the direction of the curve at a specific index (increasing or decreasing)
bool IsIncreasing(int index);

View File

@@ -544,21 +544,21 @@ string Clip::PropertiesJSON(int requested_frame) {
root["waveform"] = add_property_json("Waveform", waveform, "int", "", false, 0, -1, -1, CONSTANT, -1, false);
// Keyframes
root["location_x"] = add_property_json("Location X", location_x.GetValue(requested_frame), "float", "", location_x.Contains(requested_point), location_x.GetLength(), -10000, 10000, location_x.GetClosestPoint(requested_point).interpolation, location_x.GetClosestPoint(requested_point).co.X, false);
root["location_y"] = add_property_json("Location Y", location_y.GetValue(requested_frame), "float", "", location_y.Contains(requested_point), location_y.GetLength(), -10000, 10000, location_y.GetClosestPoint(requested_point).interpolation, location_y.GetClosestPoint(requested_point).co.X, false);
root["scale_x"] = add_property_json("Scale X", scale_x.GetValue(requested_frame), "float", "", scale_x.Contains(requested_point), scale_x.GetLength(), 0.0, 100.0, scale_x.GetClosestPoint(requested_point).interpolation, scale_x.GetClosestPoint(requested_point).co.X, false);
root["scale_y"] = add_property_json("Scale Y", scale_y.GetValue(requested_frame), "float", "", scale_y.Contains(requested_point), scale_y.GetLength(), 0.0, 100.0, scale_y.GetClosestPoint(requested_point).interpolation, scale_y.GetClosestPoint(requested_point).co.X, false);
root["alpha"] = add_property_json("Alpha", alpha.GetValue(requested_frame), "float", "", alpha.Contains(requested_point), alpha.GetLength(), 0.0, 1.0, alpha.GetClosestPoint(requested_point).interpolation, alpha.GetClosestPoint(requested_point).co.X, false);
root["rotation"] = add_property_json("Rotation", rotation.GetValue(requested_frame), "float", "", rotation.Contains(requested_point), rotation.GetLength(), -10000, 10000, rotation.GetClosestPoint(requested_point).interpolation, rotation.GetClosestPoint(requested_point).co.X, false);
root["volume"] = add_property_json("Volume", volume.GetValue(requested_frame), "float", "", volume.Contains(requested_point), volume.GetLength(), 0.0, 1.0, volume.GetClosestPoint(requested_point).interpolation, volume.GetClosestPoint(requested_point).co.X, false);
root["time"] = add_property_json("Time", time.GetValue(requested_frame), "float", "", time.Contains(requested_point), time.GetLength(), 0.0, 1000 * 60 * 30, time.GetClosestPoint(requested_point).interpolation, time.GetClosestPoint(requested_point).co.X, false);
root["location_x"] = add_property_json("Location X", location_x.GetValue(requested_frame), "float", "", location_x.Contains(requested_point), location_x.GetCount(), -10000, 10000, location_x.GetClosestPoint(requested_point).interpolation, location_x.GetClosestPoint(requested_point).co.X, false);
root["location_y"] = add_property_json("Location Y", location_y.GetValue(requested_frame), "float", "", location_y.Contains(requested_point), location_y.GetCount(), -10000, 10000, location_y.GetClosestPoint(requested_point).interpolation, location_y.GetClosestPoint(requested_point).co.X, false);
root["scale_x"] = add_property_json("Scale X", scale_x.GetValue(requested_frame), "float", "", scale_x.Contains(requested_point), scale_x.GetCount(), 0.0, 100.0, scale_x.GetClosestPoint(requested_point).interpolation, scale_x.GetClosestPoint(requested_point).co.X, false);
root["scale_y"] = add_property_json("Scale Y", scale_y.GetValue(requested_frame), "float", "", scale_y.Contains(requested_point), scale_y.GetCount(), 0.0, 100.0, scale_y.GetClosestPoint(requested_point).interpolation, scale_y.GetClosestPoint(requested_point).co.X, false);
root["alpha"] = add_property_json("Alpha", alpha.GetValue(requested_frame), "float", "", alpha.Contains(requested_point), alpha.GetCount(), 0.0, 1.0, alpha.GetClosestPoint(requested_point).interpolation, alpha.GetClosestPoint(requested_point).co.X, false);
root["rotation"] = add_property_json("Rotation", rotation.GetValue(requested_frame), "float", "", rotation.Contains(requested_point), rotation.GetCount(), -10000, 10000, rotation.GetClosestPoint(requested_point).interpolation, rotation.GetClosestPoint(requested_point).co.X, false);
root["volume"] = add_property_json("Volume", volume.GetValue(requested_frame), "float", "", volume.Contains(requested_point), volume.GetCount(), 0.0, 1.0, volume.GetClosestPoint(requested_point).interpolation, volume.GetClosestPoint(requested_point).co.X, false);
root["time"] = add_property_json("Time", time.GetValue(requested_frame), "float", "", time.Contains(requested_point), time.GetCount(), 0.0, 1000 * 60 * 30, time.GetClosestPoint(requested_point).interpolation, time.GetClosestPoint(requested_point).co.X, false);
// Keep track of settings string
stringstream properties;
properties << 0.0f << Position() << Layer() << Start() << End() << Duration() << gravity << scale << anchor << waveform <<
location_x.GetValue(requested_frame) << location_y.GetValue(requested_frame) << scale_x.GetValue(requested_frame) <<
scale_y.GetValue(requested_frame) << alpha.GetValue(requested_frame) << rotation.GetValue(requested_frame) <<
volume.GetValue(requested_frame) << time.GetValue(requested_frame);
volume.GetValue(requested_frame) << time.GetValue(requested_frame) << alpha.GetCount() << alpha.GetClosestPoint(requested_point).interpolation << alpha.GetClosestPoint(requested_point).co.X;
// Have they changed since the previous call?
bool changed = false;

View File

@@ -197,12 +197,23 @@ Point Keyframe::GetClosestPoint(Point p) {
Point existing_point = Points[x];
// find a match
if ((p.co.X <= existing_point.co.X && p.co.X >= closest.co.X) || (closest.co.X == -1)) {
if (existing_point.co.X >= p.co.X) {
// New closest point found
closest = existing_point;
break;
}
}
// Handle edge cases (if no point was found)
if (closest.co.X == -1) {
if (p.co.X < 1)
// Assign 1st point
closest = Points[0];
else
// Assign last point
closest = Points[Points.size() - 1];
}
// no matching point found
return closest;
}
@@ -416,6 +427,13 @@ int Keyframe::GetLength() {
return Values.size();
}
// Get the number of points (i.e. # of points)
int Keyframe::GetCount() {
// return the size of the Values vector
return Points.size();
}
// Remove a point by matching a coordinate
void Keyframe::RemovePoint(Point p) throw(OutOfBoundsPoint) {
// mark as dirty

View File

@@ -116,7 +116,7 @@ TEST(Clip_Properties)
try
{
// Check for specific things
CHECK_CLOSE(1.0f, root["alpha"]["value"].asDouble(), 0.00001);
CHECK_CLOSE(1.0f, root["alpha"]["value"].asDouble(), 0.01);
CHECK_EQUAL(true, root["alpha"]["keyframe"].asBool());
CHECK_EQUAL(true, root["changed"]["value"].asBool());
@@ -141,7 +141,7 @@ TEST(Clip_Properties)
try
{
// Check for specific things
CHECK_CLOSE(0.5f, root["alpha"]["value"].asDouble(), 0.001);
CHECK_CLOSE(0.5f, root["alpha"]["value"].asDouble(), 0.01);
CHECK_EQUAL(false, root["alpha"]["keyframe"].asBool());
CHECK_EQUAL(true, root["changed"]["value"].asBool());

View File

@@ -74,7 +74,7 @@ TEST(Color_HEX_Value)
c.blue.AddPoint(100, 255);
CHECK_EQUAL("#000000", c.GetColorHex(1));
CHECK_EQUAL("#818181", c.GetColorHex(50));
CHECK_EQUAL("#7f7f7f", c.GetColorHex(50));
CHECK_EQUAL("#ffffff", c.GetColorHex(100));
}

View File

@@ -223,3 +223,23 @@ TEST(Keyframe_Check_Direction_and_Repeat_Fractions)
CHECK_EQUAL(kf.GetRepeatFraction(391).den, 12);
CHECK_EQUAL(kf.GetDelta(391), -1);
}
TEST(Keyframe_Get_Closest_Point)
{
// Create a keyframe curve with 2 points
Keyframe kf;
kf.AddPoint(1, 0.0);
kf.AddPoint(1000, 1.0);
kf.AddPoint(2500, 0.0);
// Spot check values from the curve
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(900, 900)).co.X, 1000);
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(1, 1)).co.X, 1);
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(5, 5)).co.X, 1000);
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(1000, 1000)).co.X, 1000);
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(1001, 1001)).co.X, 2500);
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(2500, 2500)).co.X, 2500);
CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(3000, 3000)).co.X, 2500);
}