#include "PSTorus.h"
#include "PSTorus.c7"
#include "PSSphere.h"
#include <Stones/GravData.h>
#include <Opcode/Opcode.h>
#include <TMath.h>
#include <TRandom.h>
ClassImp(PSTorus);
void PSTorus::_init()
{
bInside = false;
mRM = 1;
mRm = 0.5;
}
void PSTorus::FindMinMaxFGH(TriMesh* mesh)
{
PARENT_GLASS::FindMinMaxH(mesh);
mMinF = -sPi; mMaxF = sPi;
mMinG = -sPi; mMaxG = sPi;
}
namespace {
inline float norm3(float x, float y, float z)
{ return sqrtf(x*x + y*y + z*z); }
}
Float_t PSTorus::Surface()
{
return 4.0f*sPi*sPi*mRM*mRm;
}
void PSTorus::pos2fgh(const Float_t* x, Float_t* f)
{
f[0] = atan2f(x[1], x[0]);
f[1] = atan2f(x[2], sqrtf(x[0]*x[0] + x[1]*x[1]) - mRM);
f[2] = norm3(x[0] - mRM*cosf(f[0]), x[1] - mRM*sinf(f[0]), x[2]) - mRm;
if (bInside) { f[0] = -f[0]; f[2] = -f[2]; }
}
void PSTorus::fgh2pos(const Float_t* f, Float_t* x)
{
const Float_t rphi = bInside ? mRm - f[2] : mRm + f[2];
const Float_t rxy = mRM + rphi*cosf(f[1]);
x[0] = rxy * cosf(f[0]);
x[1] = rxy * sinf(f[0]); if (bInside) x[1] = -x[1];
x[2] = rphi * sinf(f[1]);
}
void PSTorus::fgh2fdir(const Float_t* f, Float_t* d)
{
d[0] = -sinf(f[0]);
d[1] = cosf(f[0]);
d[2] = 0;
if (bInside) {
d[1] = -d[1];
}
}
void PSTorus::fgh2gdir(const Float_t* f, Float_t* d)
{
const Float_t st = -sinf(f[1]);
d[0] = st * cosf(f[0]);
d[1] = st * sinf(f[0]); if (bInside) d[1] = -d[1];
d[2] = cosf(f[1]);
}
void PSTorus::fgh2hdir(const Float_t* f, Float_t* d)
{
const Float_t ct = cosf(f[1]);
d[0] = ct * cosf(f[0]);
d[1] = ct * sinf(f[0]);
d[2] = sinf(f[1]);
if (bInside) {
d[0] = -d[0];
d[2] = -d[2];
}
}
void PSTorus::pos2hdir(const Float_t* x, Float_t* d)
{
const Float_t p = atan2f(x[1], x[0]);
const Float_t t = atan2f(x[2], sqrtf(x[0]*x[0] + x[1]*x[1]) - mRM);
const Float_t ct = cosf(t);
d[0] = ct*cosf(p);
d[1] = ct*sinf(p);
d[2] = sinf(t);
if (bInside) {
d[0] = -d[0]; d[1] = -d[1]; d[2] = -d[2];
}
}
Float_t PSTorus::pos2hray(const Float_t* x, Opcode::Ray& r)
{
const Float_t p = atan2f(x[1], x[0]);
const Float_t t = atan2f(x[2], sqrtf(x[0]*x[0] + x[1]*x[1]) - mRM);
const Float_t ct = cosf(t);
const Float_t sp = sinf(p), cp = cosf(p);
Float_t dr = norm3(x[0] - mRM*cp, x[1] - mRM*sp, x[2]) - mRm;
r.mDir.Set(ct*cp, ct*sp, sinf(t));
if (bInside) {
r.mDir.Neg();
dr = -dr;
}
Float_t dist = mMaxH - dr + mEpsilon;
r.mOrig.Set(x);
r.mOrig.TMac(r.mDir, dist);
r.mDir.Neg();
return dist;
}
void PSTorus::pos2grav(const Float_t* x, GravData& gd)
{
gd.fPos[0] = x[0]; gd.fPos[1] = x[1]; gd.fPos[2] = x[2];
const Float_t q = sqrtf(x[0]*x[0] + x[1]*x[1]);
Opcode::Point phi_R_shift(x[0], x[1], 0);
phi_R_shift *= mRM / q;
Opcode::Point near(x); near -= phi_R_shift;
Opcode::Point far (x); far += phi_R_shift;
GravData gd1, gd2;
GravData::lGravFraction_t gf_list;
PSSphere::fill_spherical_grav(mGravAtSurface, mRm, bInside, near, gd1);
gf_list.push_back(make_pair(1.0f, &gd1));
PSSphere::fill_spherical_grav(mGravAtSurface, mRm, bInside, far, gd2);
gf_list.push_back(make_pair(1.0f, &gd2));
gd.Combine(gf_list);
gd.fH = gd1.fH;
gd.Down() = gd1.Down();
}
void PSTorus::sub_fgh(Float_t* a, Float_t* b, Float_t* delta)
{
delta[0] = U1Sub(a[0], b[0]);
delta[1] = U1Sub(a[1], b[1]);
delta[2] = a[2] - b[2];
}
void PSTorus::regularize_fg(Float_t* f)
{
if (f[0] > sPi) f[0] -= sTwoPi;
else if (f[0] < -sPi) f[0] += sTwoPi;
if (f[1] > sPi) f[1] -= sTwoPi;
else if (f[1] < -sPi) f[1] += sTwoPi;
}
void PSTorus::random_fgh(TRandom& rnd, Float_t* f)
{
const Float_t k = mRm/mRM;
const Float_t P = rnd.Uniform(-TMath::Pi(), TMath::Pi());
Float_t t = P, d = 0;
do {
d = (P - t - k*sinf(t)) / (1 + k*cosf(t));
t += d;
} while (fabsf(d) > 1e-6);
f[0] = rnd.Uniform(-TMath::Pi(), TMath::Pi());
f[1] = t;
f[2] = 0;
}