#include "PSSphere.h"
#include "PSSphere.c7"
#include <Stones/GravData.h>
#include <Opcode/Opcode.h>
#include <TMath.h>
#include <TRandom.h>
ClassImp(PSSphere);
void PSSphere::_init()
{
bInside = false;
mR = 1;
}
void PSSphere::FindMinMaxFGH(TriMesh* mesh)
{
PARENT_GLASS::FindMinMaxH(mesh);
mMinF = -sPi; mMaxF = sPi;
mMinG = -sPiHalf; mMaxG = sPiHalf;
}
Float_t PSSphere::Surface()
{
return 4.0f*sPi*mR*mR;
}
void PSSphere::pos2fgh(const Float_t* x, Float_t* f)
{
const Float_t rxysq = x[0]*x[0] + x[1]*x[1];
const Float_t r = sqrtf(rxysq + x[2]*x[2]);
f[0] = atan2f(x[1], x[0]);
f[1] = atan2f(x[2], sqrt(rxysq));
f[2] = r - mR;
if (bInside) { f[0] = -f[0]; f[2] = -f[2]; }
}
void PSSphere::fgh2pos(const Float_t* f, Float_t* x)
{
const Float_t r = bInside ? mR - f[2] : mR + f[2];
const Float_t rct = r*cosf(f[1]);
x[0] = rct * cosf(f[0]);
x[1] = rct * sinf(f[0]); if (bInside) x[1] = -x[1];
x[2] = r * sinf(f[1]);
}
void PSSphere::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];
d[2] = -d[2];
}
}
void PSSphere::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 PSSphere::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 PSSphere::pos2hdir(const Float_t* x, Float_t* d)
{
const Float_t a = bInside ? -1.0f : 1.0f;
Float_t q = sqrtf(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
if (q != 0) {
q = a / q;
d[0] = q * x[0]; d[1] = q * x[1]; d[2] = q * x[2];
} else {
d[0] = 0; d[1] = 0; d[2] = a;
}
}
Float_t PSSphere::pos2hray(const Float_t* x, Opcode::Ray& r)
{
const Float_t a = bInside ? -1.0f : 1.0f;
Float_t q = sqrtf(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
Float_t h = bInside ? mR - q : q - mR;
Float_t dist = mMaxH - h + mEpsilon;
if (q != 0) {
q = a / q;
r.mDir.Set(q * x[0], q * x[1], q * x[2]);
} else {
r.mDir.Set(0, 0, a);
}
r.mOrig.Set(x);
r.mOrig.TMac(r.mDir, dist);
r.mDir.Neg();
return dist;
}
void PSSphere::pos2grav(const Float_t* x, GravData& gd)
{
gd.fPos[0] = x[0]; gd.fPos[1] = x[1]; gd.fPos[2] = x[2];
fill_spherical_grav(mGravAtSurface, mR, bInside, x, gd);
}
void PSSphere::sub_fgh(Float_t* a, Float_t* b, Float_t* delta)
{
delta[0] = U1Sub(a[0], b[0]);
delta[1] = a[1] - b[1];
delta[2] = a[2] - b[2];
}
void PSSphere::regularize_fg(Float_t* f)
{
if (f[0] > sPi) f[0] -= sTwoPi;
else if (f[0] < -sPi) f[0] += sTwoPi;
if (f[1] < -sPiHalf) f[1] = -sPiHalf;
else if (f[1] > sPiHalf) f[1] = sPiHalf;
}
void PSSphere::random_fgh(TRandom& rnd, Float_t* f)
{
f[0] = rnd.Uniform(-TMath::Pi(), TMath::Pi());
f[1] = TMath::ASin(rnd.Uniform(-1, 1));
f[2] = 0;
}
void PSSphere::random_pos(TRandom& rnd, Float_t* x)
{
const Float_t p = rnd.Uniform(-TMath::Pi(), TMath::Pi());
const Float_t t = TMath::ASin(rnd.Uniform(-1, 1));
const Float_t rct = mR*cosf(t);
x[0] = rct * cosf(p);
x[1] = rct * sinf(p);
x[2] = mR * sinf(t);
}
void PSSphere::fill_spherical_grav(Float_t g0, Float_t R, Bool_t inside,
const Float_t* x, GravData& gd)
{
const Float_t rr = x[0]*x[0] + x[1]*x[1] + x[2]*x[2];
const Float_t r = sqrtf(rr);
if (r > R) {
gd.fMag = g0 * R * R / rr;
gd.fLDer = gd.fTDer = gd.fMag / r;
gd.fLDer *= 2.0f;
} else {
gd.fLDer = gd.fTDer = g0 / R;
gd.fMag = gd.fLDer * r;
}
Float_t a;
if (inside) {
gd.fH = R - r;
a = 1.0f;
} else {
gd.fH = r - R;
a = -1.0f;
}
if (r != 0) {
const Float_t q = a / r;
gd.fDir[0] = q * x[0]; gd.fDir[1] = q * x[1]; gd.fDir[2] = q * x[2];
} else {
gd.fDir[0] = gd.fDir[1] = gd.fDir[2] = 0;
}
gd.fDown[0] = gd.fDir[0]; gd.fDown[1] = gd.fDir[1]; gd.fDown[2] = gd.fDir[2];
}