I need to port an excel spreadsheet that uses the solver plugin to an ASP.NET c# site, I'm using the Solver Foundation 3.1 to no avail.
The equation is iterative, and two conditions need to be met in order to determine the two decision values.
The two decision values on the spreadsheet are set to 1
Ng = 1
Nv = 1
Then the goal is to find the MAX of Formula1 when the following conditions are met:
Decision 1: Formula1 = _na
Decision 2: Formula2 = Formula3
All formulas use Ng and Nv, hitting solve changes Ng and Nv to satisfy each equation, it takes and average of 22 iterations on the spreadsheet.
I've implemented it in c# as follows:
public class FluxSolver
{
public FluxSolver(double _na, double _ygo, double _k, double _alpha, double _inletVoidFraction)
{
var solver = SolverContext.GetContext();
solver.ClearModel();
var model = solver.CreateModel();
var decisionNG = new Decision(Domain.RealNonnegative, "NG");
var decisionNV = new Decision(Domain.RealNonnegative, "NV");
model.AddDecision(decisionNG);
model.AddDecision(decisionNV);
Term formula1 = (_ygo * decisionNG) + ((1 - _ygo) * decisionNV);
model.AddGoal("Goal", GoalKind.Maximize, formula1);
model.AddConstraint("Constraint1", ((_inletVoidFraction / _k) * (1 / decisionNG)) == (_alpha * ((1 / decisionNV) - 1)));
model.AddConstraint("Constraint2", ( _ygo * decisionNG) + ((1 - _ygo) * decisionNV) == _na);
var solution = solver.Solve();
NV = decisionNV.GetDouble();
NG = decisionNG.GetDouble();
Quality = solution.Quality.ToString();
}
public double NG { get; set; }
public double NV { get; set; }
public string Quality { get; set; }
}
I've been at it for 3 days now and still not making any progress, the solver just loads and and disappears, never times out, doesn't return the values etc. Is there something fundamentally wrong in my code?
Any help appreciated!
Related
I've just jumped to the programming field. Please help me to find a reasonable solution to one of my educational projects. In case of incorrect input (for example 'z' in place of a figure) my program starts an infinite loop. I'm looking for the alternative to the infinite loop and catch use. At least, maybe someone could suggest how to empty the tray (the methods available on this site don't work with my Win7, NetBeans IDE 7.4).
OBJECTIVE
Develop a program that allows the determination of a specific number of metrics obtained in a survey.
Data
A company sponsors you for the realization of a survey system to a target prospects. According to data collected on individuals during the day, we can calculate metrics that can help the company to better target customers.
The questions used for the survey are:
Question 1: Did you like to use our product?
Question 2: If the answer to question 1 is yes, you will continue to use our product?
Question 3: Do you plan to use a product of our competitor?
Question 4: On a scale of 1 to 3 (1: bad, 2 neutral, 3 good), how do you consider the reputation of our company?
The specific task is to determine the percentages for each question. For questions 1 to 3, percentages of YES and NO are required. For question 4 the percentages of each possible choice are needed.
The data is stored in a single memory structure during the course of the program. By late afternoon, an agent terminates the program after outputting data. Therefore, we will not persist on files or databases for the moment.
Data or metrics will be posted later in the day in a clear format.
So, the purpose is to realize the capture and storage of data and to calculate metrics.
Here you are my Java code:
package surveyproject;
import java.util.Scanner;
import java.util.ArrayList;
public class SurveyProject {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList TotalSurvey = new ArrayList();
do {
try
{
System.out.println("Welcome to survey !");
System.out.println("1 - New survey");
System.out.println("2 - Publish survey results");
System.out.println("3 - Leave the program");
int new_or_printing_results_or_exit = sc.nextInt();
if (new_or_printing_results_or_exit == 1)
{
// ============== Questions 1 and 2 ================ //
System.out.println("Do you use our product? 1-yes 0-no");
int Q1_using_product = sc.nextInt();
int Q2_using_product_in_future = -1;
if (Q1_using_product == 1)
{
System.out.println("Thanks to use our product. Will you "
+ "continue to use it? 1-yes 0-no");
Q2_using_product_in_future = sc.nextInt();
}
else
{
System.out.println("That's a pity you do not use your product.");
}
// =====///====== Question 1 and 2 ================ //
// ============== Question 3 ================ //
System.out.println("Do you use the products of our competitors? 1-yes 0-no");
int Q3_using_competitor_product = sc.nextInt();
// =====///====== Question 3 ================ //
// ============== Question 4 ================ //
System.out.println("Evaluate our company.");
System.out.println("1 - Bad");
System.out.println("2 - Neutral");
System.out.println("3 - Good");
int Q4_company_reputation_rate = sc.nextInt();
// =====///====== Question 4 ================ //
System.out.println("Thank you for the participation!");
// =========== Save current Survey =========== //
Survey objSurvey = new Survey(Q1_using_product,
Q2_using_product_in_future,
Q3_using_competitor_product,
Q4_company_reputation_rate);
TotalSurvey.add(objSurvey);
// =====///=== Save current Survey =========== //
}
else if (new_or_printing_results_or_exit == 2)
{
PrintSurveyResult(TotalSurvey);
}
else if (new_or_printing_results_or_exit == 3)
{
System.out.println("Thank you to use our system!");
System.exit(0);
}
}
catch(Exception except)
{
System.out.println("You entered incorrect answer. Please,"
+ "try again the survey." );
System.out.println("Total answers: " + total_answers);
System.out.println("Question 1: ");
System.out.println("Yes answered: " + Q1_answer_yes + "(" + (double)Q1_answer_yes/total_answers * 100.0 + "%)");
System.out.println("No answered: " + Q1_answer_no + "(" + (double)Q1_answer_no/total_answers * 100.0 + "%)");
System.out.println("Question 2: ");
System.out.println("Yes answered: " + Q2_answer_yes + "(" + (double)Q2_answer_yes/total_answers * 100.0 + "%)");
System.out.println("No answered: " + Q2_answer_no + "(" + (double)Q2_answer_no/total_answers * 100.0 + "%)");
System.out.println("Question 3: ");
System.out.println("Yes answered: " + Q3_answer_yes + "(" + (double)Q3_answer_yes/total_answers * 100.0 + "%)");
System.out.println("No answered: " + Q3_answer_no + "(" + (double)Q3_answer_no/total_answers * 100.0 + "%)");
System.out.println("Question 4: ");
System.out.println("Bad answered: " + Q4_answer_bad + "(" + (double)Q4_answer_bad/total_answers * 100.0 + "%)");
System.out.println("Neutral answered: " + Q4_answer_neutral + "(" + (double)Q4_answer_neutral/total_answers * 100.0 + "%)");
System.out.println("Good answered: " + Q4_answer_good + "(" + (double)Q4_answer_good/total_answers * 100.0 + "%)");
}
}
package surveyproject;
public class Survey {
int Q1_using_product;
int Q2_using_product_in_future;
int Q3_using_competitor_product;
int Q4_company_reputation_rate;
public Survey (int Q1, int Q2, int Q3, int Q4)
{
Q1_using_product = Q1;
Q2_using_product_in_future = Q2;
Q3_using_competitor_product = Q3;
Q4_company_reputation_rate = Q4;
}
public int getQ1_using_product()
{
return Q1_using_product;
}
public int getQ2_using_product_in_future()
{
return Q2_using_product_in_future;
}
public int getQ3_using_competitor_product()
{
return Q3_using_competitor_product;
}
public int getQ4_company_reputation_rate()
{
return Q4_company_reputation_rate;
}
}
I have an assignment for my class that reads like this: Write a class called Stats. The constructor will take no input. There will be a method addData(double a) which will be used to add a value from the test program. Methods getCount(), getAverage() and getStandardDeviation() will return the appropriate values as doubles.
Here's what I have so far:
public class Stats
{
public Stats (double a)
{
a=0.0
}
public void addData(double a)
{
while (
sum=sum+a;
sumsq=sumsq+Math.pow(a,2)
count=count+1
}
public double getCount()
{
return count;
}
public double getAverage()
{
average=sum/count
return average;
}
public double getStandardDeviation()
{
private double sum=o;
private double count=0;
private double sumsq=0;
My problem is figuring out how to calculate the standard deviation using the variables I've defined.
Thanks guys!
You can't do this with the variables you defined. You need to keep the original data to be able to compute the formula
sigma = Math.sqrt( sum(Math.pow(x-mean, 2)) / count )
So,
(1) create private array or list into which you'll add your values in addData. That's all you need to do in addData.
(2) getCount = length of the list
(3) getAverage = sum of values in list / getCount()
(4) getStandardDeviation is something like
double avg = getAverage();
double cnt = getCount();
double sumsq = 0;
for (int i = 0; i < values.Count(); i++) {
sumsq += Math.pow(values[i] - avg, 2);
}
stdev = Math.sqrt(sumsq / cnt);
We want to receive list of nearby places from database using LINQ in ASP.NET 2012 and would like some feedback on our strategy.
My table and fake data:
PlaceId Name Latitude Longitude
1 A 18.1 20.1
2 B 18.2 20.2
3 C 18.3 20.3
1) In our project the client current location (latitude and longitude) is taken as input
2) At server side ,depending upon the client current location, we need to find nearby places from the database using LINQ
Here's the code for SQL which I earlier used , but now we want to use LINQ.
SELECT name, Latitude, Longitude ,
( 3959 * acos( cos( radians(?) )* cos( radians( Latitude) ) * cos( radians( Longitude ) - radians(?) )
+ sin( radians(?) ) * sin( radians( Latitude) ) ) ) AS distance
FROM TABLE_NAME
HAVING distance < ?
ORDER BY distance LIMIT 0 , 20
[But the question is how to write such an query in LINQ.]
My work on this:
While searching for the solution, I came across this code
var Value1 = 57.2957795130823D;
var Value2 = 3958.75586574D;
var searchWithin = 20;
double latitude = ConversionHelper.SafeConvertToDoubleCultureInd(Latitude, 0),
longitude = ConversionHelper.SafeConvertToDoubleCultureInd(Longitude, 0);
var location = (from l in sdbml.Places
let temp = Math.Sin(Convert.ToDouble(l.Latitude) / Value1) * Math.Sin(Convert.ToDouble(latitude) / Value1) +
Math.Cos(Convert.ToDouble(l.Latitude) / Value1) *
Math.Cos(Convert.ToDouble(latitude) / Value1) *
Math.Cos((Convert.ToDouble(longitude) / Value1) - (Convert.ToDouble(l.Longitude) / Value1))
let calMiles = (Value2 * Math.Acos(temp > 1 ? 1 : (temp < -1 ? -1 : temp)))
where (l.Latitude > 0 && l.Longitude > 0)
orderby calMiles
select new location
{
Name = l.name
});
return location .ToList();
But the problem is ,how to reference ConversionHelper or under which namespace it comes.
All advice is appreciated.
so, if all that you want is to calculate distance between two co-ordinates, why don't you use Dot Net's GeoCoordinate?
it goes something like
var firstCordinate = new GeoCoordinate(latitude1, longitude1);
var secondCordinate = new GeoCoordinate(latitude2, longitude2);
double distance = firstCordinate.GetDistanceTo(secondCordinate);
you can find it inside namespace System.Device.Location.
So this will save you from all those Math.Cos and Math.Sin and your linq will be plain and simple. (probably a foreach loop will do)
so your entire query can be summarized as:
List<Location> locations = new List<Location>();
foreach(var place in sdbml.Places)
{
//your logic to compare various place's co-ordinates with that of
//user's current co-ordinate
}
Here is the code which finally I have to settle down with
1)Create a class , say
DistanceModel.cs
public class DistanceModel
{
public int PlaceId { get; set; }
public string Name { get; set; }
public double Latitute { get; set; }
public double Longitude { get; set; }
}
2)Then include the below code in whichever file you want to , say
MainPage.cs
/*Call GetAllNearestFamousPlaces() method to get list of nearby places depending
upon user current location.
Note: GetAllNearestFamousPlaces() method takes 2 parameters as input
that is GetAllNearestFamousPlaces(user_current_Latitude,user_current_Longitude) */
public void GetAllNearestFamousPlaces(double currentLatitude,double currentLongitude)
{
List<DistanceModel> Caldistance = new List<DistanceModel>();
var query = (from c in sdbml.Places
select c).ToList();
foreach (var place in query)
{
double distance = Distance(currentLatitude, currentLongitude, place.Latitude, place.Logitude);
if (distance < 25) //nearbyplaces which are within 25 kms
{
DistanceModel dist = new DistanceModel();
dist.Name = place.PlaceName;
dist.Latitute = place.Latitude;
dist.Longitude = place.Logitude;
dist.PlaceId = place.PlaceId;
Caldistance.Add(getDiff);
}
}
}
private double Distance(double lat1, double lon1, double lat2, double lon2)
{
double theta = lon1 - lon2;
double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
dist = Math.Acos(dist);
dist = rad2deg(dist);
dist = (dist * 60 * 1.1515) / 0.6213711922; //miles to kms
return (dist);
}
private double deg2rad(double deg)
{
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad)
{
return (rad * 180.0 / Math.PI);
}
It worked for me, Hope it will help you to .
I am trying to scale a skeleton to match to the sizes of another skeleton.
My algoritm do the following:
Find the distance between two joints of the origin skeleton and the destiny skeleton using phytagorean teorem
divide this two distances to find a multiply factor.
Multiply each joint by this factor.
Here is my actual code:
public static Skeleton ScaleToMatch(this Skeleton skToBeScaled, Skeleton skDestiny)
{
Joint newJoint = new Joint();
double distanciaOrigem = 0;
double distanciaDestino = 0;
double fator = 1;
SkeletonPoint pos = new SkeletonPoint();
foreach (BoneOrientation bo in skToBeScaled.BoneOrientations)
{
distanciaOrigem = FisioKinectCalcs.Distance3DBetweenJoint(skToBeScaled.Joints[bo.StartJoint], skToBeScaled.Joints[bo.EndJoint]);
distanciaDestino = FisioKinectCalcs.Distance3DBetweenJoint(skDestiny.Joints[bo.StartJoint], skDestiny.Joints[bo.EndJoint]);
if (distanciaOrigem > 0 && distanciaDestino > 0)
{
fator = (distanciaDestino / distanciaOrigem);
newJoint = skToBeScaled.Joints[bo.EndJoint]; // escaling only the end joint as the BoneOrientatios starts from HipCenter, i am scaling from center to edges.
// applying the new values to the joint
pos = new SkeletonPoint()
{
X = (float)(newJoint.Position.X * fator),
Y = (float)(newJoint.Position.Y * fator),
Z = (float)(newJoint.Position.Z * fator)
};
newJoint.Position = pos;
skToBeScaled.Joints[bo.EndJoint] = newJoint;
}
}
return skToBeScaled;
}
Every seems to work fine except for the hands and foots
Look at this images
I have my own skeleton over me, and my skeleton scaled to the sizes of another person, but the hands and foots still crazy. (but code looks right)
Any suggestion?
It's hard to say without running the code, but it somewhat "looks good".
What I would validate though, is your
if (distanciaOrigem > 0 && distanciaDestino > 0)
If distanciaOrigem is very close to 0, but even just epsilon away from 0, it won't be picked up by the if, and then
fator = (distanciaDestino / distanciaOrigem);
Will result in a very large number!
I would suggest to smooth the factor so it generally fits the proper scale. Try this code:
private static Dictionary<JointType, double> jointFactors = null;
static CalibrationUtils()
{
InitJointFactors();
}
public static class EnumUtil
{
public static IEnumerable<T> GetValues<T>()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
}
private static void InitJointFactors()
{
var jointTypes = EnumUtil.GetValues<JointType>();
jointFactors = new Dictionary<JointType, double>();
foreach(JointType type in jointTypes)
{
jointFactors.Add(type, 0);
}
}
private static double SmoothenFactor(JointType jointType, double factor, int weight)
{
double currentValue = jointFactors[jointType];
double newValue = 0;
if(currentValue != 0)
newValue = (weight * currentValue + factor) / (weight + 1);
else
newValue = factor;
jointFactors[jointType] = newValue;
return newValue;
}
When it comes to factor usage just use the SmoothenFactor method first:
public static Skeleton ScaleToMatch(this Skeleton skToBeScaled, Skeleton skDestiny, double additionalFactor = 1)
{
Joint newJoint = new Joint();
double distanceToScale = 0;
double distanceDestiny = 0;
double factor = 1;
int weight = 500;
SkeletonPoint pos = new SkeletonPoint();
Skeleton newSkeleton = null;
KinectHelper.CopySkeleton(skToBeScaled, ref newSkeleton);
SkeletonPoint hipCenterPosition = newSkeleton.Joints[JointType.HipCenter].Position;
foreach(BoneOrientation bo in skToBeScaled.BoneOrientations)
{
distanceToScale = Distance3DBetweenJoints(skToBeScaled.Joints[bo.StartJoint], skToBeScaled.Joints[bo.EndJoint]);
distanceDestiny = Distance3DBetweenJoints(skDestiny.Joints[bo.StartJoint], skDestiny.Joints[bo.EndJoint]);
if(distanceToScale > 0 && distanceDestiny > 0)
{
factor = (distanceDestiny / distanceToScale) * additionalFactor;
newJoint = skToBeScaled.Joints[bo.EndJoint]; // escaling only the end joint as the BoneOrientatios starts from HipCenter, i am scaling from center to edges.
factor = SmoothenFactor(newJoint.JointType, factor, weight);
pos = new SkeletonPoint()
{
X = (float)((newJoint.Position.X - hipCenterPosition.X) * factor + hipCenterPosition.X),
Y = (float)((newJoint.Position.Y - hipCenterPosition.Y) * factor + hipCenterPosition.Y),
Z = (float)((newJoint.Position.Z - hipCenterPosition.Z) * factor + hipCenterPosition.Z)
};
newJoint.Position = pos;
newSkeleton.Joints[bo.EndJoint] = newJoint;
}
}
return newSkeleton;
}
I also modified your ScaleToMatch method as you see. There was a need to move joints in relation to HipCenter position. Also new positions are saved to a new Skeleton instance so they are not used in further vector calculations.
Experiment with the weight but since our bones length is constant you can use big numbers like 100 and more to be sure that wrong Kinect readings do not disturb the correct scale.
Here's an example of how it helped with scaling HandRight joint position:
The weight was set to 500. The resulting factor is supposed to be around 2 (because the base skeleton was purposely downscaled by a factor of 2).
I hope it helps!
To implement a 2D animation I am looking for interpolating values between two key frames with the velocity of change defined by a Bezier curve. The problem is Bezier curve is represented in parametric form whereas requirement is to be able to evaluate the value for a particular time.
To elaborate, lets say the value of 10 and 40 is to be interpolated across 4 seconds with the value changing not constantly but as defined by a bezier curve represented as 0,0 0.2,0.3 0.5,0.5 1,1.
Now if I am drawing at 24 frames per second, I need to evaluate the value for every frame. How can I do this ? I looked at De Casteljau algorithm and thought that dividing the curve into 24*4 pieces for 4 seconds would solve my problem but that sounds erroneous as time is along the "x" axis and not along the curve.
To further simplify
If I draw the curve in a plane, the x axis represents the time and the y axis the value I am looking for. What I actually require is to to be able to find out "y" corresponding to "x". Then I can divide x in 24 divisions and know the value for each frame
I was facing the same problem: Every animation package out there seems to use Bézier curves to control values over time, but there is no information out there on how to implement a Bézier curve as a y(x) function. So here is what I came up with.
A standard cubic Bézier curve in 2D space can be defined by the four points P0=(x0, y0) .. P3=(x3, y3).
P0 and P3 are the end points of the curve, while P1 and P2 are the handles affecting its shape. Using a parameter t ϵ [0, 1], the x and y coordinates for any given point along the curve can then be determined using the equations
A) x = (1-t)3x0 + 3t(1-t)2x1 + 3t2(1-t)x2 + t3x3 and
B) y = (1-t)3y0 + 3t(1-t)2y1 + 3t2(1-t)y2 + t3y3.
What we want is a function y(x) that, given an x coordinate, will return the corresponding y coordinate of the curve. For this to work, the curve must move monotonically from left to right, so that it doesn't occupy the same x coordinate more than once on different y positions. The easiest way to ensure this is to restrict the input points so that x0 < x3 and x1, x2 ϵ [x0, x3]. In other words, P0 must be to the left of P3 with the two handles between them.
In order to calculate y for a given x, we must first determine t from x. Getting y from t is then a simple matter of applying t to equation B.
I see two ways of determining t for a given y.
First, you might try a binary search for t. Start with a lower bound of 0 and an upper bound of 1 and calculate x for these values for t via equation A. Keep bisecting the interval until you get a reasonably close approximation. While this should work fine, it will neither be particularly fast nor very precise (at least not both at once).
The second approach is to actually solve equation A for t. That's a bit tough to implement because the equation is cubic. On the other hand, calculation becomes really fast and yields precise results.
Equation A can be rewritten as
(-x0+3x1-3x2+x3)t3 + (3x0-6x1+3x2)t2 + (-3x0+3x1)t + (x0-x) = 0.
Inserting your actual values for x0..x3, we get a cubic equation of the form at3 + bt2 + c*t + d = 0 for which we know there is only one solution within [0, 1]. We can now solve this equation using an algorithm like the one posted in this Stack Overflow answer.
The following is a little C# class demonstrating this approach. It should be simple enough to convert it to a language of your choice.
using System;
public class Point {
public Point(double x, double y) {
X = x;
Y = y;
}
public double X { get; private set; }
public double Y { get; private set; }
}
public class BezierCurve {
public BezierCurve(Point p0, Point p1, Point p2, Point p3) {
P0 = p0;
P1 = p1;
P2 = p2;
P3 = p3;
}
public Point P0 { get; private set; }
public Point P1 { get; private set; }
public Point P2 { get; private set; }
public Point P3 { get; private set; }
public double? GetY(double x) {
// Determine t
double t;
if (x == P0.X) {
// Handle corner cases explicitly to prevent rounding errors
t = 0;
} else if (x == P3.X) {
t = 1;
} else {
// Calculate t
double a = -P0.X + 3 * P1.X - 3 * P2.X + P3.X;
double b = 3 * P0.X - 6 * P1.X + 3 * P2.X;
double c = -3 * P0.X + 3 * P1.X;
double d = P0.X - x;
double? tTemp = SolveCubic(a, b, c, d);
if (tTemp == null) return null;
t = tTemp.Value;
}
// Calculate y from t
return Cubed(1 - t) * P0.Y
+ 3 * t * Squared(1 - t) * P1.Y
+ 3 * Squared(t) * (1 - t) * P2.Y
+ Cubed(t) * P3.Y;
}
// Solves the equation ax³+bx²+cx+d = 0 for x ϵ ℝ
// and returns the first result in [0, 1] or null.
private static double? SolveCubic(double a, double b, double c, double d) {
if (a == 0) return SolveQuadratic(b, c, d);
if (d == 0) return 0;
b /= a;
c /= a;
d /= a;
double q = (3.0 * c - Squared(b)) / 9.0;
double r = (-27.0 * d + b * (9.0 * c - 2.0 * Squared(b))) / 54.0;
double disc = Cubed(q) + Squared(r);
double term1 = b / 3.0;
if (disc > 0) {
double s = r + Math.Sqrt(disc);
s = (s < 0) ? -CubicRoot(-s) : CubicRoot(s);
double t = r - Math.Sqrt(disc);
t = (t < 0) ? -CubicRoot(-t) : CubicRoot(t);
double result = -term1 + s + t;
if (result >= 0 && result <= 1) return result;
} else if (disc == 0) {
double r13 = (r < 0) ? -CubicRoot(-r) : CubicRoot(r);
double result = -term1 + 2.0 * r13;
if (result >= 0 && result <= 1) return result;
result = -(r13 + term1);
if (result >= 0 && result <= 1) return result;
} else {
q = -q;
double dum1 = q * q * q;
dum1 = Math.Acos(r / Math.Sqrt(dum1));
double r13 = 2.0 * Math.Sqrt(q);
double result = -term1 + r13 * Math.Cos(dum1 / 3.0);
if (result >= 0 && result <= 1) return result;
result = -term1 + r13 * Math.Cos((dum1 + 2.0 * Math.PI) / 3.0);
if (result >= 0 && result <= 1) return result;
result = -term1 + r13 * Math.Cos((dum1 + 4.0 * Math.PI) / 3.0);
if (result >= 0 && result <= 1) return result;
}
return null;
}
// Solves the equation ax² + bx + c = 0 for x ϵ ℝ
// and returns the first result in [0, 1] or null.
private static double? SolveQuadratic(double a, double b, double c) {
double result = (-b + Math.Sqrt(Squared(b) - 4 * a * c)) / (2 * a);
if (result >= 0 && result <= 1) return result;
result = (-b - Math.Sqrt(Squared(b) - 4 * a * c)) / (2 * a);
if (result >= 0 && result <= 1) return result;
return null;
}
private static double Squared(double f) { return f * f; }
private static double Cubed(double f) { return f * f * f; }
private static double CubicRoot(double f) { return Math.Pow(f, 1.0 / 3.0); }
}
You have a few options:
Let's say your curve function F(t) takes a parameter t that ranges from 0 to 1 where F(0) is the beginning of the curve and F(1) is the end of the curve.
You could animate motion along the curve by incrementing t at a constant change per unit of time.
So t is defined by function T(time) = Constant*time
For example, if your frame is 1/24th of a second, and you want to move along the curve at a rate of 0.1 units of t per second, then each frame you increment t by 0.1 (t/s) * 1/24 (sec/frame).
A drawback here is that your actual speed or distance traveled per unit time will not be constant. It will depends on the positions of your control points.
If you want to scale speed along the curve uniformly you can modify the constant change in t per unit time. However, if you want speeds to vary dramatically you will find it difficult to control the shape of the curve. If you want the velocity at one endpoint to be much larger, you must move the control point further away, which in turn pulls the shape of the curve towards that point. If this is a problem, you may consider using a non constant function for t. There are a variety of approaches with different trade-offs, and we need to know more details about your problem to suggest a solution. For example, in the past I have allowed users to define the speed at each keyframe and used a lookup table to translate from time to parameter t such that there is a linear change in speed between keyframe speeds (it's complicated).
Another common hangup: If you are animating by connecting several Bezier curves, and you want the velocity to be continuous when moving between curves, then you will need to constrain your control points so they are symmetrical with the adjacent curve. Catmull-Rom splines are a common approach.
I've answered a similar question here. Basically if you know the control points before hand then you can transform the f(t) function into a y(x) function. To not have to do it all by hand you can use services like Wolfram Alpha to help you with the math.