11bool InPolyhedron(
const std::vector<Garfield::Panel>& panels,
12 const double x,
const double y,
const double z,
13 const bool inv =
false) {
15 for (
const auto& panel : panels) {
16 double d = panel.a * (panel.xv[0] -
x) + panel.b * (panel.yv[0] - y) +
17 panel.c * (panel.zv[0] -
z);
19 if (d < 0.)
return false;
30 :
Solid(cx, cy, cz,
"SolidSphere") {
36 const double rmin,
const double rmax)
37 :
Solid(cx, cy, cz,
"SolidSphere") {
43 const bool tesselated)
const {
45 const double dx = x -
m_cX;
46 const double dy = y -
m_cY;
47 const double dz = z -
m_cZ;
49 if (fabs(dx) > m_rMax || fabs(dy) > m_rMax || fabs(dz) > m_rMax) {
52 const double r = sqrt(dx * dx + dy * dy + dz * dz);
53 if (!tesselated)
return (r >= m_rMin && r <= m_rMax);
54 if (r > m_rMax || !InPolyhedron(m_panelsO, dx, dy, dz))
return false;
56 return (r >= m_rMin || !InPolyhedron(m_panelsI, dx, dy, dz,
true));
62 double& xmax,
double& ymax,
75 std::cerr <<
"SolidSphere::SetRadius: Radius must be > 0.\n";
85 std::cerr <<
"SolidSphere::SetRadii: Outer radius must be > 0.\n";
89 std::cerr <<
"SolidSphere::SetRadii:\n"
90 <<
" Outer radius must be > inner radius.\n";
100 std::cerr <<
"SolidSphere::SetMeridians: Number must be >= 3.\n";
109 const auto nPanels = panels.size();
110 panels.insert(panels.begin(), m_panelsO.begin(), m_panelsO.end());
111 panels.insert(panels.begin(), m_panelsI.begin(), m_panelsI.end());
112 std::cout <<
"SolidSphere::SolidPanels: " << panels.size() - nPanels
117void SolidSphere::UpdatePanels() {
118 std::lock_guard<std::mutex> guard(m_mutex);
121 const auto id =
GetId();
122 MakePanels(
id, m_rMax,
true, m_panelsO);
124 MakePanels(
id, m_rMin,
false, m_panelsI);
128void SolidSphere::MakePanels(
const int vol,
const double r,
const bool out,
129 std::vector<Panel>& panels)
const {
131 const double dphi = TwoPi / m_n;
132 const double dtheta = Pi / m_n;
134 for (
unsigned int i = 1; i <= m_n; ++i) {
135 const double phi0 = (i - 1.) * dphi;
136 const double phi1 = phi0 + dphi;
137 const double cphi0 =
cos(phi0);
138 const double sphi0 =
sin(phi0);
139 const double cphi1 =
cos(phi1);
140 const double sphi1 =
sin(phi1);
141 for (
unsigned int j = 1; j <= m_n; ++j) {
142 const double theta0 = -HalfPi + (j - 1.) * dtheta;
143 const double theta1 = theta0 + dtheta;
144 const double ctheta0 =
cos(theta0);
145 const double stheta0 =
sin(theta0);
146 const double ctheta1 =
cos(theta1);
147 const double stheta1 =
sin(theta1);
151 const double xv0 =
m_cX + r * cphi0 * ctheta0;
152 const double yv0 =
m_cY + r * sphi0 * ctheta0;
153 const double zv0 =
m_cZ + r * stheta0;
154 const double xv1 =
m_cX + r * cphi1 * ctheta1;
155 const double yv1 =
m_cY + r * sphi1 * ctheta1;
156 const double zv1 =
m_cZ + r * stheta1;
157 const double xv2 =
m_cX + r * cphi0 * ctheta1;
158 const double yv2 =
m_cY + r * sphi0 * ctheta1;
159 const double zv2 =
m_cZ + r * stheta1;
160 panel.xv = {xv0, xv1, xv2};
161 panel.yv = {yv0, yv1, yv2};
162 panel.zv = {zv0, zv1, zv2};
163 }
else if (j == m_n) {
164 const double xv0 =
m_cX + r * cphi0 * ctheta0;
165 const double yv0 =
m_cY + r * sphi0 * ctheta0;
166 const double zv0 =
m_cZ + r * stheta0;
167 const double xv1 =
m_cX + r * cphi1 * ctheta0;
168 const double yv1 =
m_cY + r * sphi1 * ctheta0;
169 const double zv1 =
m_cZ + r * stheta0;
170 const double xv2 =
m_cX + r * cphi1 * ctheta1;
171 const double yv2 =
m_cY + r * sphi1 * ctheta1;
172 const double zv2 =
m_cZ + r * stheta1;
173 panel.xv = {xv0, xv1, xv2};
174 panel.yv = {yv0, yv1, yv2};
175 panel.zv = {zv0, zv1, zv2};
177 const double xv0 =
m_cX + r * cphi0 * ctheta0;
178 const double yv0 =
m_cY + r * sphi0 * ctheta0;
179 const double zv0 =
m_cZ + r * stheta0;
180 const double xv1 =
m_cX + r * cphi1 * ctheta0;
181 const double yv1 =
m_cY + r * sphi1 * ctheta0;
182 const double zv1 =
m_cZ + r * stheta0;
183 const double xv2 =
m_cX + r * cphi1 * ctheta1;
184 const double yv2 =
m_cY + r * sphi1 * ctheta1;
185 const double zv2 =
m_cZ + r * stheta1;
186 const double xv3 =
m_cX + r * cphi0 * ctheta1;
187 const double yv3 =
m_cY + r * sphi0 * ctheta1;
188 const double zv3 =
m_cZ + r * stheta1;
189 panel.xv = {xv0, xv1, xv2, xv3};
190 panel.yv = {yv0, yv1, yv2, yv3};
191 panel.zv = {zv0, zv1, zv2, zv3};
195 atan2((ctheta0 - ctheta1) *
sqrt((1. +
cos(phi1 - phi0)) / 2),
197 const double calpha =
cos(alpha);
198 const double salpha =
sin(alpha);
201 panel.a =
cos(0.5 * (phi0 + phi1)) * calpha;
202 panel.b =
sin(0.5 * (phi0 + phi1)) * calpha;
205 panel.a = -
cos(0.5 * (phi0 + phi1)) * calpha;
206 panel.b = -
sin(0.5 * (phi0 + phi1)) * calpha;
210 panels.push_back(std::move(panel));
220 const double xn,
const double yn,
const double zn,
221 std::vector<Panel>& panels) {
226 std::vector<double> xv;
227 std::vector<double> yv;
228 std::vector<double> zv;
230 const double r = m_rMax;
231 for (
unsigned int i = 1; i <= m_n; ++i) {
233 const double phi0 = TwoPi * (i - 1.) / m_n;
234 const double phi1 = TwoPi * i / m_n;
235 for (
unsigned int j = 1; j <= m_n; ++j) {
237 const double theta0 = -HalfPi + Pi * (j - 1.) / m_n;
238 const double theta1 = -HalfPi + Pi * j / m_n;
240 const double x1 = x0 + r * cos(phi0) * cos(theta0);
241 const double y1 = y0 + r * sin(phi0) * cos(theta0);
242 const double z1 = z0 + r * sin(theta0);
245 const double x2 = x0 + r * cos(phi1) * cos(theta0);
246 const double y2 = y0 + r * sin(phi1) * cos(theta0);
247 const double z2 = z0 + r * sin(theta0);
251 x0, y0, z0, xn, yn, zn, xc, yc, zc)) {
258 const double x2 = x0 + r * cos(phi0) * cos(theta1);
259 const double y2 = y0 + r * sin(phi0) * cos(theta1);
260 const double z2 = z0 + r * sin(theta1);
264 x0, y0, z0, xn, yn, zn, xc, yc, zc)) {
274 if (xv.size() >= 3) {
284 panels.push_back(std::move(panel));
bool IsInside(const double x, const double y, const double z, const bool tesselated) const override
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) const override
Return the bounding box of the solid.
void SetRadii(const double rmin, const double rmax)
Set the inner and outer radius of the sphere.
void SetRadius(const double r)
Set the radius of the sphere.
void Cut(const double x0, const double y0, const double z0, const double xn, const double yn, const double zn, std::vector< Panel > &panels) override
double GetDiscretisationLevel(const Panel &panel) override
Retrieve the discretisation level of a panel.
bool SolidPanels(std::vector< Panel > &panels) override
Retrieve the surface panels of the solid.
SolidSphere(const double cx, const double cy, const double cz, const double r)
Constructor from centre and outer radius.
void SetMeridians(const unsigned int n)
Abstract base class for solids.
static bool Intersect(const double x1, const double y1, const double z1, const double x2, const double y2, const double z2, const double x0, const double y0, const double z0, const double a, const double b, const double c, double &xc, double &yc, double &zc)
unsigned int GetId() const
Get the ID of the solid.
double m_cX
Centre of the solid.
void EliminateButterflies(std::vector< double > &xp, std::vector< double > &yp, std::vector< double > &zp)
DoubleAc cos(const DoubleAc &f)
DoubleAc sin(const DoubleAc &f)
DoubleAc sqrt(const DoubleAc &f)
std::vector< double > zv
Z-coordinates of vertices.
int volume
Reference to solid to which the panel belongs.
double a
Perpendicular vector.
std::vector< double > xv
X-coordinates of vertices.
std::vector< double > yv
Y-coordinates of vertices.