11 const std::vector<double>& xp,
12 const std::vector<double>& yp)
13 :
Solid(0, 0, 0,
"SolidExtrusion"), m_lZ(lz) {
18 const std::vector<double>& xp,
19 const std::vector<double>& yp,
20 const double cx,
const double cy,
22 const double dx,
const double dy,
34 if (m_xp.empty())
return false;
36 double u = x, v = y, w = z;
38 if (fabs(w) > m_lZ)
return false;
39 bool inside =
false, edge =
false;
45 double& xmax,
double& ymax,
double& zmax)
const {
47 if (m_xp.empty())
return false;
48 const double x0 = *std::min_element(m_xp.begin(), m_xp.end());
49 const double x1 = *std::max_element(m_xp.begin(), m_xp.end());
50 const double y0 = *std::min_element(m_yp.begin(), m_yp.end());
51 const double y1 = *std::max_element(m_yp.begin(), m_yp.end());
53 const double r = std::max({fabs(x0), fabs(y0), fabs(x1), fabs(y1)});
54 const double d = sqrt(r * r + m_lZ * m_lZ);
68 std::cerr <<
"SolidExtrusion::SetHalfLengthZ: Half-length must be > 0.\n";
73 const std::vector<double>& yp) {
75 if (xp.size() != yp.size()) {
76 std::cerr <<
"SolidExtrusion::SetProfile:\n"
77 <<
" Mismatch between number of x and y coordinates.\n";
80 const auto np = xp.size();
82 std::cerr <<
"SolidExtrusion::SetProfile: Too few points; rejected.\n";
86 std::cerr <<
"SolidExtrusion::SetProfile: Not a valid polygon.\n";
89 const auto it = std::max_element(xp.begin(), xp.end());
90 const unsigned int i0 = std::distance(xp.begin(), it);
91 const unsigned int i1 = i0 < np - 1 ? i0 + 1 : 0;
92 const unsigned int i2 = i1 < np - 1 ? i1 + 1 : 0;
93 const double det = (xp[i1] - xp[i0]) * (yp[i2] - yp[i0]) -
94 (xp[i2] - xp[i0]) * (yp[i1] - yp[i0]);
97 }
else if (det > 0.) {
100 std::cerr <<
"SolidExtrusion::SetProfile:\n"
101 <<
" Unable to determine profile orientation;"
102 <<
" assuming it is clockwise.\n";
113 const auto id =
GetId();
114 const auto nPanels = panels.size();
116 std::cerr <<
"SolidExtrusion::SolidPanels: Profile is not defined.\n";
122 std::cerr <<
"SolidExtrusion::SolidPanels:\n"
123 <<
" Zero norm direction vector; no panels generated.\n";
126 const double a =
m_dX / fnorm;
127 const double b =
m_dY / fnorm;
128 const double c =
m_dZ / fnorm;
130 const unsigned int np = m_xp.size();
137 for (
unsigned int i = 0; i < np; ++i) {
140 ToGlobal(m_xp[i], m_yp[i], m_lZ, x, y, z);
141 panel.
xv.push_back(x);
142 panel.
yv.push_back(y);
143 panel.
zv.push_back(z);
147 panels.push_back(std::move(panel));
155 for (
unsigned int i = 0; i < np; ++i) {
158 ToGlobal(m_xp[i], m_yp[i], -m_lZ, x, y, z);
159 panel.
xv.push_back(x);
160 panel.
yv.push_back(y);
161 panel.
zv.push_back(z);
165 panels.push_back(std::move(panel));
170 ToGlobal(m_xp.back(), m_yp.back(), -m_lZ, x0, y0, z0);
172 ToGlobal(m_xp.back(), m_yp.back(), +m_lZ, x1, y1, z1);
174 for (
unsigned int i = 0; i < np; ++i) {
177 ToGlobal(m_xp[i], m_yp[i], +m_lZ, x2, y2, z2);
179 ToGlobal(m_xp[i], m_yp[i], -m_lZ, x3, y3, z3);
181 const unsigned int k = i == 0 ? np - 1 : i - 1;
182 double xn = m_yp[k] - m_yp[i];
183 double yn = m_xp[i] - m_xp[k];
184 const double fn = sqrt(xn * xn + yn * yn);
186 std::cerr <<
"SolidExtrusion::SolidPanels: Zero norm edge (warning).\n";
200 panel.
xv = {x0, x1, x2, x3};
201 panel.
yv = {y0, y1, y2, y3};
202 panel.
zv = {z0, z1, z2, z3};
205 panels.push_back(std::move(panel));
216 std::cout <<
"SolidExtrusion::SolidPanels: " << panels.size() - nPanels
224 double u = 0., v = 0., w = 0.;
227 if (w > std::max(fabs(u), fabs(v))) {
229 }
else if (w < -std::max(fabs(u), fabs(v))) {
236 const double xn,
const double yn,
const double zn,
237 std::vector<Panel>& panels) {
243 std::vector<double> xv;
244 std::vector<double> yv;
245 std::vector<double> zv;
246 const unsigned int np = m_xp.size();
249 ToGlobal(m_xp.back(), m_yp.back(), m_lZ, x1, y1, z1);
251 for (
unsigned int i = 0; i < np; ++i) {
253 ToGlobal(m_xp[i], m_yp[i], m_lZ, x2, y2, z2);
257 x0, y0, z0, xn, yn, zn, xc, yc, zc)) {
270 ToGlobal(m_xp.back(), m_yp.back(), -m_lZ, x1, y1, z1);
272 for (
unsigned int i = 0; i < np; ++i) {
274 ToGlobal(m_xp[i], m_yp[i], -m_lZ, x2, y2, z2);
277 x0, y0, z0, xn, yn, zn, xc, yc, zc)) {
288 for (
unsigned int i = 0; i < np; ++i) {
290 ToGlobal(m_xp[i], m_yp[i], +m_lZ, x1, y1, z1);
292 ToGlobal(m_xp[i], m_yp[i], -m_lZ, x2, y2, z2);
295 x0, y0, z0, xn, yn, zn, xc, yc, zc)) {
304 if (xv.size() >= 3) {
314 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.
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.
void SetHalfLengthZ(const double lz)
Set the half-length of the extrusion.
void SetProfile(const std::vector< double > &xp, const std::vector< double > &yp)
Set the coordinates of the extrusion profile.
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
SolidExtrusion(const double lz, const std::vector< double > &xp, const std::vector< double > &yp)
Constructor from half-length and profile.
Abstract base class for solids.
void VectorToLocal(const double x, const double y, const double z, double &u, double &v, double &w)
Transform a vector from global to local coordinates.
double m_cTheta
Polar angle.
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)
double m_dX
Direction vector.
unsigned int GetId() const
Get the ID of the solid.
void ToLocal(const double x, const double y, const double z, double &u, double &v, double &w) const
void SetDirection(const double dx, const double dy, const double dz)
void ToGlobal(const double u, const double v, const double w, double &x, double &y, double &z) const
double m_cX
Centre of the solid.
double m_cPhi
Azimuthal angle.
bool NonTrivial(const std::vector< double > &xp, const std::vector< double > &yp)
Check whether a set of points builds a non-trivial polygon.
void EliminateButterflies(std::vector< double > &xp, std::vector< double > &yp, std::vector< double > &zp)
void Inside(const std::vector< double > &xpl, const std::vector< double > &ypl, const double x, const double y, bool &inside, bool &edge)
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.