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);
152 const double xv0 =
m_cX + r * cphi0 * ctheta0;
153 const double yv0 =
m_cY + r * sphi0 * ctheta0;
154 const double zv0 =
m_cZ + r * stheta0;
155 const double xv1 =
m_cX + r * cphi1 * ctheta1;
156 const double yv1 =
m_cY + r * sphi1 * ctheta1;
157 const double zv1 =
m_cZ + r * stheta1;
158 const double xv2 =
m_cX + r * cphi0 * ctheta1;
159 const double yv2 =
m_cY + r * sphi0 * ctheta1;
160 const double zv2 =
m_cZ + r * stheta1;
161 panel.xv = {xv0, xv1, xv2};
162 panel.yv = {yv0, yv1, yv2};
163 panel.zv = {zv0, zv1, zv2};
164 }
else if (j == m_n) {
165 const double xv0 =
m_cX + r * cphi0 * ctheta0;
166 const double yv0 =
m_cY + r * sphi0 * ctheta0;
167 const double zv0 =
m_cZ + r * stheta0;
168 const double xv1 =
m_cX + r * cphi1 * ctheta0;
169 const double yv1 =
m_cY + r * sphi1 * ctheta0;
170 const double zv1 =
m_cZ + r * stheta0;
171 const double xv2 =
m_cX + r * cphi1 * ctheta1;
172 const double yv2 =
m_cY + r * sphi1 * ctheta1;
173 const double zv2 =
m_cZ + r * stheta1;
174 panel.xv = {xv0, xv1, xv2};
175 panel.yv = {yv0, yv1, yv2};
176 panel.zv = {zv0, zv1, zv2};
178 const double xv0 =
m_cX + r * cphi0 * ctheta0;
179 const double yv0 =
m_cY + r * sphi0 * ctheta0;
180 const double zv0 =
m_cZ + r * stheta0;
181 const double xv1 =
m_cX + r * cphi1 * ctheta0;
182 const double yv1 =
m_cY + r * sphi1 * ctheta0;
183 const double zv1 =
m_cZ + r * stheta0;
184 const double xv2 =
m_cX + r * cphi1 * ctheta1;
185 const double yv2 =
m_cY + r * sphi1 * ctheta1;
186 const double zv2 =
m_cZ + r * stheta1;
187 const double xv3 =
m_cX + r * cphi0 * ctheta1;
188 const double yv3 =
m_cY + r * sphi0 * ctheta1;
189 const double zv3 =
m_cZ + r * stheta1;
190 panel.xv = {xv0, xv1, xv2, xv3};
191 panel.yv = {yv0, yv1, yv2, yv3};
192 panel.zv = {zv0, zv1, zv2, zv3};
196 atan2((ctheta0 - ctheta1) *
sqrt((1. +
cos(phi1 - phi0)) / 2),
198 const double calpha =
cos(alpha);
199 const double salpha =
sin(alpha);
202 panel.a =
cos(0.5 * (phi0 + phi1)) * calpha;
203 panel.b =
sin(0.5 * (phi0 + phi1)) * calpha;
206 panel.a = -
cos(0.5 * (phi0 + phi1)) * calpha;
207 panel.b = -
sin(0.5 * (phi0 + phi1)) * calpha;
211 panels.push_back(std::move(panel));
221 const double xn,
const double yn,
const double zn,
222 std::vector<Panel>& panels) {
227 std::vector<double> xv;
228 std::vector<double> yv;
229 std::vector<double> zv;
231 const double r = m_rMax;
232 for (
unsigned int i = 1; i <= m_n; ++i) {
234 const double phi0 = TwoPi * (i - 1.) / m_n;
235 const double phi1 = TwoPi * i / m_n;
236 for (
unsigned int j = 1; j <= m_n; ++j) {
238 const double theta0 = -HalfPi + Pi * (j - 1.) / m_n;
239 const double theta1 = -HalfPi + Pi * j / m_n;
241 const double x1 = x0 + r * cos(phi0) * cos(theta0);
242 const double y1 = y0 + r * sin(phi0) * cos(theta0);
243 const double z1 = z0 + r * sin(theta0);
246 const double x2 = x0 + r * cos(phi1) * cos(theta0);
247 const double y2 = y0 + r * sin(phi1) * cos(theta0);
248 const double z2 = z0 + r * sin(theta0);
252 x0, y0, z0, xn, yn, zn, xc, yc, zc)) {
259 const double x2 = x0 + r * cos(phi0) * cos(theta1);
260 const double y2 = y0 + r * sin(phi0) * cos(theta1);
261 const double z2 = z0 + r * sin(theta1);
265 x0, y0, z0, xn, yn, zn, xc, yc, zc)) {
275 if (xv.size() >= 3) {
285 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)
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.
Solid()=delete
Default constructor.
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.