ROOT logo
// $Id: PSSphere.cxx 2182 2009-04-12 23:11:16Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

#include "PSSphere.h"
#include "PSSphere.c7"
#include <Stones/GravData.h>

#include <Opcode/Opcode.h>

#include <TMath.h>
#include <TRandom.h>

//==============================================================================
// PSSphere
//==============================================================================

//__________________________________________________________________________
//
// Parametric sphere surface.
// bInside ~ false: 'world' on outer surface, like a planet.
// bInside ~ true:  'world' on inner surface, like Dyson sphere.
//
//   | Outside             | Inside
//-----------------------------------------------
// f | phi   [  -pi, pi  ] | phi   [inverted]
// g | theta [-pi/2, pi/2] | theta [same    ]
// h | dr    [  -mR, inf ] | dr    [mR, -inf]
//
// f,g,h vectors form a right-handed ortho-normal base.
// 'outside' -> 'inside' : { f -> -f, h -> -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]); // cos is even
  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[0] = -d[0]; already negated by phi inversion and oddness of sin
    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[1] = -d[1]; already negated by phi inversion and oddness of sin
    d[2] = -d[2];
  }
}

/**************************************************************************/

void PSSphere::pos2hdir(const Float_t* x, Float_t* d)
{
  // Return 'up' direction.

  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)
{
  // Setup ray r for given postition x so that the ray origin is above
  // the surface and its direction/lenght ascertain the surface will
  // be intersected.
  // Returns distance the ray-origin was shifted from initial pos.

  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;

  // printf("a=%f; q=%f; dr=%f; dist=%f;\n", a, q, dr, dist);

  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();
  /*
  printf("pos=%.2f,%.2f,%.2f; orig=%.2f,%.2f,%.2f; dir=%.2f,%.2f,%.2f; dist=%.2f\n",
         x[0],      x[1],      x[2],
         r.mOrig.x, r.mOrig.y, r.mOrig.z,
         r.mDir.x,  r.mDir.y,  r.mDir.z,
         dist);
  */
  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);

  /*
  const Float_t rr = x[0]*x[0] + x[1]*x[1] + x[2]*x[2];
  const Float_t r  = sqrtf(rr);

  if (r > mR) {
    gd.fMag   = mGravAtSurface * mR * mR / rr;
    gd.fLDer  = gd.fTDer = gd.fMag / r;
    gd.fLDer *= 2.0f;    
  } else {
    gd.fLDer = gd.fTDer = mGravAtSurface / mR;
    gd.fMag  = gd.fLDer * r;
  }

  Float_t a;
  if (bInside) {
    gd.fH = mR - r;
    a     = 1.0f;
  } else {
    gd.fH =  r - mR;
    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;
  }
  */
}

/**************************************************************************/

void PSSphere::sub_fgh(Float_t* a, Float_t* b, Float_t* delta)
{
  // Subtract fgh values, taking care of U(1) variables (like angles).
  // Here this is done for phi.

  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)
{
  // Put fg values into regular intervals.

  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)
{
  // Fills passed GravData as determined by other parameters.
  // GravData::fPos is not set.

  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;
  }

  // Copy down direction.
  gd.fDown[0] = gd.fDir[0]; gd.fDown[1] = gd.fDir[1]; gd.fDown[2] = gd.fDir[2];
}
 PSSphere.cxx:1
 PSSphere.cxx:2
 PSSphere.cxx:3
 PSSphere.cxx:4
 PSSphere.cxx:5
 PSSphere.cxx:6
 PSSphere.cxx:7
 PSSphere.cxx:8
 PSSphere.cxx:9
 PSSphere.cxx:10
 PSSphere.cxx:11
 PSSphere.cxx:12
 PSSphere.cxx:13
 PSSphere.cxx:14
 PSSphere.cxx:15
 PSSphere.cxx:16
 PSSphere.cxx:17
 PSSphere.cxx:18
 PSSphere.cxx:19
 PSSphere.cxx:20
 PSSphere.cxx:21
 PSSphere.cxx:22
 PSSphere.cxx:23
 PSSphere.cxx:24
 PSSphere.cxx:25
 PSSphere.cxx:26
 PSSphere.cxx:27
 PSSphere.cxx:28
 PSSphere.cxx:29
 PSSphere.cxx:30
 PSSphere.cxx:31
 PSSphere.cxx:32
 PSSphere.cxx:33
 PSSphere.cxx:34
 PSSphere.cxx:35
 PSSphere.cxx:36
 PSSphere.cxx:37
 PSSphere.cxx:38
 PSSphere.cxx:39
 PSSphere.cxx:40
 PSSphere.cxx:41
 PSSphere.cxx:42
 PSSphere.cxx:43
 PSSphere.cxx:44
 PSSphere.cxx:45
 PSSphere.cxx:46
 PSSphere.cxx:47
 PSSphere.cxx:48
 PSSphere.cxx:49
 PSSphere.cxx:50
 PSSphere.cxx:51
 PSSphere.cxx:52
 PSSphere.cxx:53
 PSSphere.cxx:54
 PSSphere.cxx:55
 PSSphere.cxx:56
 PSSphere.cxx:57
 PSSphere.cxx:58
 PSSphere.cxx:59
 PSSphere.cxx:60
 PSSphere.cxx:61
 PSSphere.cxx:62
 PSSphere.cxx:63
 PSSphere.cxx:64
 PSSphere.cxx:65
 PSSphere.cxx:66
 PSSphere.cxx:67
 PSSphere.cxx:68
 PSSphere.cxx:69
 PSSphere.cxx:70
 PSSphere.cxx:71
 PSSphere.cxx:72
 PSSphere.cxx:73
 PSSphere.cxx:74
 PSSphere.cxx:75
 PSSphere.cxx:76
 PSSphere.cxx:77
 PSSphere.cxx:78
 PSSphere.cxx:79
 PSSphere.cxx:80
 PSSphere.cxx:81
 PSSphere.cxx:82
 PSSphere.cxx:83
 PSSphere.cxx:84
 PSSphere.cxx:85
 PSSphere.cxx:86
 PSSphere.cxx:87
 PSSphere.cxx:88
 PSSphere.cxx:89
 PSSphere.cxx:90
 PSSphere.cxx:91
 PSSphere.cxx:92
 PSSphere.cxx:93
 PSSphere.cxx:94
 PSSphere.cxx:95
 PSSphere.cxx:96
 PSSphere.cxx:97
 PSSphere.cxx:98
 PSSphere.cxx:99
 PSSphere.cxx:100
 PSSphere.cxx:101
 PSSphere.cxx:102
 PSSphere.cxx:103
 PSSphere.cxx:104
 PSSphere.cxx:105
 PSSphere.cxx:106
 PSSphere.cxx:107
 PSSphere.cxx:108
 PSSphere.cxx:109
 PSSphere.cxx:110
 PSSphere.cxx:111
 PSSphere.cxx:112
 PSSphere.cxx:113
 PSSphere.cxx:114
 PSSphere.cxx:115
 PSSphere.cxx:116
 PSSphere.cxx:117
 PSSphere.cxx:118
 PSSphere.cxx:119
 PSSphere.cxx:120
 PSSphere.cxx:121
 PSSphere.cxx:122
 PSSphere.cxx:123
 PSSphere.cxx:124
 PSSphere.cxx:125
 PSSphere.cxx:126
 PSSphere.cxx:127
 PSSphere.cxx:128
 PSSphere.cxx:129
 PSSphere.cxx:130
 PSSphere.cxx:131
 PSSphere.cxx:132
 PSSphere.cxx:133
 PSSphere.cxx:134
 PSSphere.cxx:135
 PSSphere.cxx:136
 PSSphere.cxx:137
 PSSphere.cxx:138
 PSSphere.cxx:139
 PSSphere.cxx:140
 PSSphere.cxx:141
 PSSphere.cxx:142
 PSSphere.cxx:143
 PSSphere.cxx:144
 PSSphere.cxx:145
 PSSphere.cxx:146
 PSSphere.cxx:147
 PSSphere.cxx:148
 PSSphere.cxx:149
 PSSphere.cxx:150
 PSSphere.cxx:151
 PSSphere.cxx:152
 PSSphere.cxx:153
 PSSphere.cxx:154
 PSSphere.cxx:155
 PSSphere.cxx:156
 PSSphere.cxx:157
 PSSphere.cxx:158
 PSSphere.cxx:159
 PSSphere.cxx:160
 PSSphere.cxx:161
 PSSphere.cxx:162
 PSSphere.cxx:163
 PSSphere.cxx:164
 PSSphere.cxx:165
 PSSphere.cxx:166
 PSSphere.cxx:167
 PSSphere.cxx:168
 PSSphere.cxx:169
 PSSphere.cxx:170
 PSSphere.cxx:171
 PSSphere.cxx:172
 PSSphere.cxx:173
 PSSphere.cxx:174
 PSSphere.cxx:175
 PSSphere.cxx:176
 PSSphere.cxx:177
 PSSphere.cxx:178
 PSSphere.cxx:179
 PSSphere.cxx:180
 PSSphere.cxx:181
 PSSphere.cxx:182
 PSSphere.cxx:183
 PSSphere.cxx:184
 PSSphere.cxx:185
 PSSphere.cxx:186
 PSSphere.cxx:187
 PSSphere.cxx:188
 PSSphere.cxx:189
 PSSphere.cxx:190
 PSSphere.cxx:191
 PSSphere.cxx:192
 PSSphere.cxx:193
 PSSphere.cxx:194
 PSSphere.cxx:195
 PSSphere.cxx:196
 PSSphere.cxx:197
 PSSphere.cxx:198
 PSSphere.cxx:199
 PSSphere.cxx:200
 PSSphere.cxx:201
 PSSphere.cxx:202
 PSSphere.cxx:203
 PSSphere.cxx:204
 PSSphere.cxx:205
 PSSphere.cxx:206
 PSSphere.cxx:207
 PSSphere.cxx:208
 PSSphere.cxx:209
 PSSphere.cxx:210
 PSSphere.cxx:211
 PSSphere.cxx:212
 PSSphere.cxx:213
 PSSphere.cxx:214
 PSSphere.cxx:215
 PSSphere.cxx:216
 PSSphere.cxx:217
 PSSphere.cxx:218
 PSSphere.cxx:219
 PSSphere.cxx:220
 PSSphere.cxx:221
 PSSphere.cxx:222
 PSSphere.cxx:223
 PSSphere.cxx:224
 PSSphere.cxx:225
 PSSphere.cxx:226
 PSSphere.cxx:227
 PSSphere.cxx:228
 PSSphere.cxx:229
 PSSphere.cxx:230
 PSSphere.cxx:231
 PSSphere.cxx:232
 PSSphere.cxx:233
 PSSphere.cxx:234
 PSSphere.cxx:235
 PSSphere.cxx:236
 PSSphere.cxx:237
 PSSphere.cxx:238
 PSSphere.cxx:239
 PSSphere.cxx:240
 PSSphere.cxx:241
 PSSphere.cxx:242
 PSSphere.cxx:243
 PSSphere.cxx:244
 PSSphere.cxx:245
 PSSphere.cxx:246
 PSSphere.cxx:247
 PSSphere.cxx:248
 PSSphere.cxx:249
 PSSphere.cxx:250
 PSSphere.cxx:251
 PSSphere.cxx:252
 PSSphere.cxx:253
 PSSphere.cxx:254
 PSSphere.cxx:255
 PSSphere.cxx:256
 PSSphere.cxx:257
 PSSphere.cxx:258
 PSSphere.cxx:259
 PSSphere.cxx:260
 PSSphere.cxx:261
 PSSphere.cxx:262
 PSSphere.cxx:263
 PSSphere.cxx:264
 PSSphere.cxx:265
 PSSphere.cxx:266
 PSSphere.cxx:267
 PSSphere.cxx:268
 PSSphere.cxx:269
 PSSphere.cxx:270
 PSSphere.cxx:271
 PSSphere.cxx:272
 PSSphere.cxx:273
 PSSphere.cxx:274
 PSSphere.cxx:275
 PSSphere.cxx:276
 PSSphere.cxx:277
 PSSphere.cxx:278
 PSSphere.cxx:279
 PSSphere.cxx:280
 PSSphere.cxx:281
 PSSphere.cxx:282
 PSSphere.cxx:283
 PSSphere.cxx:284
 PSSphere.cxx:285
 PSSphere.cxx:286
 PSSphere.cxx:287