Skip to content

Instantly share code, notes, and snippets.

@dharmatech
Created December 8, 2012 02:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dharmatech/4238289 to your computer and use it in GitHub Desktop.
Save dharmatech/4238289 to your computer and use it in GitHub Desktop.
#include "stdafx.h"
#include "..\..\include\symbolicc++.h"
Symbolic Pi = "Pi";
Symbolic g = "g";
Symbolic Radians(Symbolic n) { return n * Pi / 180; }
Symbolic Degrees(Symbolic n) { return 180 * n / Pi; }
class Point
{
public:
Symbolic x;
Symbolic y;
Point() { x = "NOTSET" ; y = "NOTSET"; }
Point(Symbolic x_val, Symbolic y_val)
{
x = x_val;
y = y_val;
}
void Print()
{
cout << "Point(" << x << ", " << y << ")";
}
static Point FromAngle(Symbolic angle, Symbolic mag)
{ return Point(cos(angle) * mag, sin(angle) * mag); }
Point operator+(Point p) { return Point(x + p.x, y + p.y); }
Point operator*(Symbolic sym) { return Point(x * sym, y * sym); }
Point operator/(Symbolic sym) { return Point(x / sym, y / sym); }
Symbolic Norm() { return sqrt(x*x + y*y); }
double ToAngle() { return atan2(y, x); }
};
void Unset(Symbolic &sym) { sym = "NOTSET"; }
bool IsSet(Symbolic sym)
{
if (sym == "NOTSET")
return false;
else
return true;
}
bool HasVal(Symbolic sym)
{
if (sym == "NOTSET")
return false;
else
return true;
}
class Obj
{
public:
Point position, velocity, acceleration;
Symbolic speed;
Symbolic time;
void Print()
{
// cout << "Obj:" << endl;
cout << "time: " << time << endl;
cout << "position.x: " << position.x << endl;
cout << "position.y: " << position.y << endl;
cout << "velocity.x: " << velocity.x << endl;
cout << "velocity.y: " << velocity.y << endl;
cout << "acceleration.x: " << acceleration.x << endl;
cout << "acceleration.y: " << acceleration.y << endl;
}
Obj AtTime(Symbolic t)
{
Obj obj;
obj.time = t;
auto dt = t - time;
obj.acceleration = acceleration;
obj.velocity = velocity + acceleration * dt;
obj.position = position + velocity * dt + acceleration * dt * dt / 2;
return obj;
}
};
Symbolic CalcTime(Obj& a, Obj& b, int flag=0)
{
if (HasVal(b.velocity.x) &&
HasVal(a.velocity.x) &&
HasVal(a.acceleration.x) &&
a.acceleration.x != 0.0 &&
a.acceleration.x != 0)
return (b.velocity.x - a.velocity.x) / a.acceleration.x;
if (HasVal(b.velocity.y) &&
HasVal(a.velocity.y) &&
HasVal(a.acceleration.y) &&
a.acceleration.y != 0.0 &&
a.acceleration.y != 0)
return (b.velocity.y - a.velocity.y) / a.acceleration.y;
if (HasVal(a.position.x) &&
HasVal(b.position.x) &&
HasVal(a.velocity.x) &&
a.velocity.x != 0 &&
a.velocity.x != 0.0)
return (b.position.x - a.position.x) / a.velocity.x;
if (HasVal(b.position.x) &&
HasVal(a.position.x) &&
HasVal(a.velocity.x) &&
HasVal(a.acceleration.x) &&
a.acceleration.x != 0 &&
a.acceleration.x != 0.0)
{
if (flag == 0)
return
(-a.velocity.x + sqrt(pow(a.velocity.x, Symbolic(2)) - 2 * a.acceleration.x * (a.position.x - b.position.x)))
/
a.acceleration.x;
else
return
(-a.velocity.x - sqrt(pow(a.velocity.x, Symbolic(2)) - 2 * a.acceleration.x * (a.position.x - b.position.x)))
/
a.acceleration.x;
}
if (HasVal(a.position.y) &&
HasVal(b.position.y) &&
HasVal(a.velocity.y) &&
HasVal(a.acceleration.y) &&
a.acceleration.y != 0 &&
a.acceleration.y != 0.0)
{
if (flag == 0)
return
(-a.velocity.y + sqrt(pow(a.velocity.y, Symbolic(2)) - 2 * a.acceleration.y * (a.position.y - b.position.y)))
/
a.acceleration.y;
else
return
(-a.velocity.y - sqrt(pow(a.velocity.y, Symbolic(2)) - 2 * a.acceleration.y * (a.position.y - b.position.y)))
/
a.acceleration.y;
}
throw "exception";
}
Symbolic CalcInitialVelocityX(Obj& a, Obj& b)
{
if (HasVal(a.position.x) &&
HasVal(a.position.y) &&
HasVal(a.time) &&
HasVal(b.time) &&
HasVal(a.acceleration.x))
{
auto dt = b.time - a.time;
return (b.position.x - a.position.x - a.acceleration.x * dt^2 / 2) / dt;
}
throw "exception";
}
auto _g = Point(0, -g);
double SymmetricalAbout(double a, double b) { return a + a - b; }
// sin(a th) = b
Symbolic SineCalcTheta(Symbolic a, Symbolic b, int solution = 0, int n = 0)
{
if (solution == 0) return (- asin(b) + 2 * Pi * n + Pi) / a;
if (solution == 1) return (asin(b) + 2 * Pi * n) / a;
}
Symbolic CalcInitialAngle(Obj a, Obj b, int sol = 0, int n = 0)
{
if (HasVal(a.position.x) &&
HasVal(b.position.x) &&
HasVal(a.acceleration.y) &&
HasVal(a.speed))
if (sol == 0)
return (- asin(- a.acceleration.y * (b.position.x - a.position.x) / (a.speed^2)) + 2 * Pi * n + Pi) / 2;
if (sol == 1)
return (asin(- a.acceleration.y * (b.position.x - a.position.x) / (a.speed^2)) + 2 * Pi * n) / 2;
throw "exception";
}
int _tmain(int argc, _TCHAR* argv[])
{
// One strategy in a snowball fight is to throw a first
// snowball at a high angle over level ground. While your
// opponent is watching the first one, you throw a second one
// at a low angle and timed to arrive at your opponent
// before or at the same time as the first one. Assume both
// snowballs are thrown with a speed of 25.0 m/s. The first
// one is thrown at an angle of 70.0° with respect to the
// horizontal. (a) At what angle should the second
// (low-angle) snowball be thrown if it is to land at the same
// point as the first? (b) How many seconds later should
// the second snowball be thrown if it is to land at the
// same time as the first?
{
Obj obj1A;
Obj obj1B;
obj1A.time = 0;
obj1A.position.x = 0;
obj1A.position.y = 0;
auto pi = 3.14159;
obj1A.velocity = Point::FromAngle(Radians(70)[Pi == pi], 25);
_g = Point(0, -9.8);
obj1A.acceleration = _g;
obj1B.position.y = 0;
obj1B.velocity.x = obj1A.velocity.x;
obj1B.acceleration = _g;
auto time1B = CalcTime(obj1A, obj1B, 1);
// cout << "showball 1 at initial position: " << endl;
// obj1A.Print();
obj1B = obj1A.AtTime(time1B);
// cout << "showball 1 at final position: " << endl;
// obj1B.Print();
Obj obj2A;
Obj obj2B;
obj2A.position = obj1A.position;
obj2A.speed = 25;
obj2A.acceleration = _g;
obj2B.position = obj1B.position;
obj2B.acceleration = _g;
auto angle2 = CalcInitialAngle(obj2A, obj2B, 1);
cout << "showball 2 should be thrown at angle: "
<< Degrees(angle2)[Pi == pi] << endl;
obj2A.velocity = Point::FromAngle(angle2, 25);
// time it takes for snowball 2 to go from A to B:
auto time2AB = CalcTime(obj2A, obj2B, 0);
// They land at the same time:
obj2B.time = obj1B.time;
// Calculate start time:
obj2A.time = obj2B.time - time2AB;
cout << "snowball 2 should be thrown at time: " << obj2A.time << endl;
}
system("pause");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment