PeriDEM 0.3.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
openCuboidChannel3D.cpp
Go to the documentation of this file.
1/*
2 * -------------------------------------------
3 * Copyright (c) 2021 - 2026 Prashant K. Jha
4 * -------------------------------------------
5 * PeriDEM https://github.com/prashjha/PeriDEM
6 *
7 * Distributed under the Boost Software License, Version 1.0.
8 */
9
10#include "openCuboidChannel3D.h"
11#include "geomUtilFunctions.h"
12#include "util/io.h"
13#include <algorithm>
14#include <cmath>
15#include <sstream>
16#include <stdexcept>
17
18namespace geom {
19
20namespace {
21
22void validateParams(double x0, double y0, double z0, double x1, double y1, double z1, double t,
23 int open_face) {
24 constexpr double eps = 1.0e-12;
25 if (!(x1 > x0 + eps && y1 > y0 + eps && z1 > z0 + eps && t > eps))
26 throw std::runtime_error(
27 "OpenCuboidChannel3D: require x0<x1, y0<y1, z0<z1, t>0.");
28 if (!(x1 - x0 > 2. * t + eps && y1 - y0 > 2. * t + eps && z1 - z0 > 2. * t + eps))
29 throw std::runtime_error(
30 "OpenCuboidChannel3D: each outer span must exceed 2*t so the inner cavity exists.");
31 if (open_face < 0 || open_face > 5)
32 throw std::runtime_error("OpenCuboidChannel3D: open_face must be in 0..5 (±x,±y,±z).");
33}
34
35void cornersFromAabb(const util::Point &lo, const util::Point &hi, util::Point *out8) {
36 const double x0 = lo.d_x, y0 = lo.d_y, z0 = lo.d_z;
37 const double x1 = hi.d_x, y1 = hi.d_y, z1 = hi.d_z;
38 out8[0] = {x0, y0, z0};
39 out8[1] = {x1, y0, z0};
40 out8[2] = {x1, y1, z0};
41 out8[3] = {x0, y1, z0};
42 out8[4] = {x0, y0, z1};
43 out8[5] = {x1, y0, z1};
44 out8[6] = {x1, y1, z1};
45 out8[7] = {x0, y1, z1};
46}
47
49 lo = hi = c[0];
50 for (int i = 1; i < 8; ++i) {
51 lo.d_x = std::min(lo.d_x, c[i].d_x);
52 lo.d_y = std::min(lo.d_y, c[i].d_y);
53 lo.d_z = std::min(lo.d_z, c[i].d_z);
54 hi.d_x = std::max(hi.d_x, c[i].d_x);
55 hi.d_y = std::max(hi.d_y, c[i].d_y);
56 hi.d_z = std::max(hi.d_z, c[i].d_z);
57 }
58}
59
60} // namespace
61
63 : GeomObject("open_cuboid_channel_3d", "") {}
64
65OpenCuboidChannel3D::OpenCuboidChannel3D(double x0, double y0, double z0, double x1, double y1, double z1,
66 double t, int open_face, std::string description)
67 : GeomObject("open_cuboid_channel_3d", std::move(description)),
68 d_lo(x0, y0, z0),
69 d_hi(x1, y1, z1),
70 d_t(t),
71 d_openFace(open_face) {
72 validateParams(x0, y0, z0, x1, y1, z1, t, open_face);
74}
75
77 : GeomObject(other.d_name, other.d_description),
78 d_lo(other.d_lo),
79 d_hi(other.d_hi),
80 d_t(other.d_t),
81 d_openFace(other.d_openFace),
82 d_x(other.d_x) {
83 d_tags = other.d_tags;
84}
85
87 if (this != &other) {
88 d_tags = other.d_tags;
89 d_lo = other.d_lo;
90 d_hi = other.d_hi;
91 d_t = other.d_t;
92 d_openFace = other.d_openFace;
93 d_x = other.d_x;
94 }
95 return *this;
96}
97
99
101 const auto &L = d_lo;
102 const auto &H = d_hi;
103 const double t = d_t;
104 const bool in_outer =
105 p.d_x >= L.d_x && p.d_x <= H.d_x && p.d_y >= L.d_y && p.d_y <= H.d_y && p.d_z >= L.d_z &&
106 p.d_z <= H.d_z;
107 const double xi0 = L.d_x + t, xi1 = H.d_x - t;
108 const double yi0 = L.d_y + t, yi1 = H.d_y - t;
109 const double zi0 = L.d_z + t, zi1 = H.d_z - t;
110 const bool in_inner =
111 p.d_x >= xi0 && p.d_x <= xi1 && p.d_y >= yi0 && p.d_y <= yi1 && p.d_z >= zi0 && p.d_z <= zi1;
112 return in_outer && !in_inner;
113}
114
116 if (!inClosedShell(p))
117 return false;
118 const auto &L = d_lo;
119 const auto &H = d_hi;
120 const double t = d_t;
121 constexpr double eps = 1.0e-12;
122 const double x0 = L.d_x, y0 = L.d_y, z0 = L.d_z;
123 const double x1 = H.d_x, y1 = H.d_y, z1 = H.d_z;
124
125 switch (d_openFace) {
126 case 0: { // +x: slab x in [x1-t, x1], (y,z) annulus on +x face
127 if (p.d_x < x1 - t - eps || p.d_x > x1 + eps)
128 return false;
129 const bool oyz = p.d_y >= y0 && p.d_y <= y1 && p.d_z >= z0 && p.d_z <= z1;
130 const bool iyz =
131 p.d_y >= y0 + t && p.d_y <= y1 - t && p.d_z >= z0 + t && p.d_z <= z1 - t;
132 return oyz && !iyz;
133 }
134 case 1: { // -x
135 if (p.d_x < x0 - eps || p.d_x > x0 + t + eps)
136 return false;
137 const bool oyz = p.d_y >= y0 && p.d_y <= y1 && p.d_z >= z0 && p.d_z <= z1;
138 const bool iyz =
139 p.d_y >= y0 + t && p.d_y <= y1 - t && p.d_z >= z0 + t && p.d_z <= z1 - t;
140 return oyz && !iyz;
141 }
142 case 2: { // +y
143 if (p.d_y < y1 - t - eps || p.d_y > y1 + eps)
144 return false;
145 const bool oxz = p.d_x >= x0 && p.d_x <= x1 && p.d_z >= z0 && p.d_z <= z1;
146 const bool ixz =
147 p.d_x >= x0 + t && p.d_x <= x1 - t && p.d_z >= z0 + t && p.d_z <= z1 - t;
148 return oxz && !ixz;
149 }
150 case 3: { // -y
151 if (p.d_y < y0 - eps || p.d_y > y0 + t + eps)
152 return false;
153 const bool oxz = p.d_x >= x0 && p.d_x <= x1 && p.d_z >= z0 && p.d_z <= z1;
154 const bool ixz =
155 p.d_x >= x0 + t && p.d_x <= x1 - t && p.d_z >= z0 + t && p.d_z <= z1 - t;
156 return oxz && !ixz;
157 }
158 case 4: { // +z: roof slab
159 if (p.d_z < z1 - t - eps || p.d_z > z1 + eps)
160 return false;
161 const bool oxy = p.d_x >= x0 && p.d_x <= x1 && p.d_y >= y0 && p.d_y <= y1;
162 const bool ixy =
163 p.d_x >= x0 + t && p.d_x <= x1 - t && p.d_y >= y0 + t && p.d_y <= y1 - t;
164 return oxy && !ixy;
165 }
166 case 5: { // -z
167 if (p.d_z < z0 - eps || p.d_z > z0 + t + eps)
168 return false;
169 const bool oxy = p.d_x >= x0 && p.d_x <= x1 && p.d_y >= y0 && p.d_y <= y1;
170 const bool ixy =
171 p.d_x >= x0 + t && p.d_x <= x1 - t && p.d_y >= y0 + t && p.d_y <= y1 - t;
172 return oxy && !ixy;
173 }
174 default:
175 return false;
176 }
177}
178
180 const double Lx = d_hi.d_x - d_lo.d_x;
181 const double Ly = d_hi.d_y - d_lo.d_y;
182 const double Lz = d_hi.d_z - d_lo.d_z;
183 const double t = d_t;
184 const double Vout = Lx * Ly * Lz;
185 const double Vin = std::max(0., (Lx - 2. * t) * (Ly - 2. * t) * (Lz - 2. * t));
186 const double Vclosed = Vout - Vin;
187 const double cx = 0.5 * (d_lo.d_x + d_hi.d_x);
188 const double cy = 0.5 * (d_lo.d_y + d_hi.d_y);
189 const double cz = 0.5 * (d_lo.d_z + d_hi.d_z);
190 util::Point c_closed(cx, cy, cz);
191 if (Vclosed <= 1.0e-30)
192 return c_closed;
193
194 if (d_openFace < 0 || d_openFace > 5)
195 return c_closed;
196
197 double Aface = 0.;
198 util::Point c_roof(cx, cy, cz);
199 if (d_openFace == 0 || d_openFace == 1) {
200 Aface = Ly * Lz - std::max(0., (Ly - 2. * t) * (Lz - 2. * t));
201 c_roof.d_x = (d_openFace == 0) ? d_hi.d_x - 0.5 * t : d_lo.d_x + 0.5 * t;
202 c_roof.d_y = cy;
203 c_roof.d_z = cz;
204 } else if (d_openFace == 2 || d_openFace == 3) {
205 Aface = Lx * Lz - std::max(0., (Lx - 2. * t) * (Lz - 2. * t));
206 c_roof.d_y = (d_openFace == 2) ? d_hi.d_y - 0.5 * t : d_lo.d_y + 0.5 * t;
207 c_roof.d_x = cx;
208 c_roof.d_z = cz;
209 } else {
210 Aface = Lx * Ly - std::max(0., (Lx - 2. * t) * (Ly - 2. * t));
211 c_roof.d_z = (d_openFace == 4) ? d_hi.d_z - 0.5 * t : d_lo.d_z + 0.5 * t;
212 c_roof.d_x = cx;
213 c_roof.d_y = cy;
214 }
215 const double Vroof = Aface * t;
216 const double Vopen = Vclosed - Vroof;
217 if (Vopen <= 1.0e-30)
218 return c_closed;
219 return (1. / Vopen) * (Vclosed * c_closed - Vroof * c_roof);
220}
221
222void OpenCuboidChannel3D::transform(const util::Point &translation, const double &scale,
223 const double &angle, const util::Point &axis,
224 const util::Point *rotationPoint) {
225 const util::Point c0 = d_x;
226 d_t *= scale;
227 util::Point c[8];
228 cornersFromAabb(d_lo, d_hi, c);
229 for (int i = 0; i < 8; ++i)
230 c[i] = mapSimilarity(c[i], c0, translation, scale, angle, axis, rotationPoint);
231 aabbFromCorners(c, d_lo, d_hi);
232 validateParams(d_lo.d_x, d_lo.d_y, d_lo.d_z, d_hi.d_x, d_hi.d_y, d_hi.d_z, d_t, d_openFace);
233 d_x = computeCenter();
234}
235
237 const double Lx = d_hi.d_x - d_lo.d_x;
238 const double Ly = d_hi.d_y - d_lo.d_y;
239 const double Lz = d_hi.d_z - d_lo.d_z;
240 const double t = d_t;
241 const double Vout = Lx * Ly * Lz;
242 const double Vin = std::max(0., (Lx - 2. * t) * (Ly - 2. * t) * (Lz - 2. * t));
243 const double Vclosed = Vout - Vin;
244 double Aface = 0.;
245 if (d_openFace == 0 || d_openFace == 1)
246 Aface = Ly * Lz - std::max(0., (Ly - 2. * t) * (Lz - 2. * t));
247 else if (d_openFace == 2 || d_openFace == 3)
248 Aface = Lx * Lz - std::max(0., (Lx - 2. * t) * (Lz - 2. * t));
249 else
250 Aface = Lx * Ly - std::max(0., (Lx - 2. * t) * (Ly - 2. * t));
251 const double Vroof = Aface * t;
252 return std::max(0., Vclosed - Vroof);
253}
254
256
257std::pair<util::Point, util::Point> OpenCuboidChannel3D::box() const { return box(0.); }
258
259std::pair<util::Point, util::Point> OpenCuboidChannel3D::box(const double &tol) const {
260 return {d_lo - tol, d_hi + tol};
261}
262
263double OpenCuboidChannel3D::inscribedRadius() const { return 0.5 * d_t; }
264
266 const util::Point &c = d_x;
267 util::Point c8[8];
268 cornersFromAabb(d_lo, d_hi, c8);
269 double r = 0.;
270 for (int i = 0; i < 8; ++i)
271 r = std::max(r, (c8[i] - c).length());
272 return r;
273}
274
276 return inClosedShell(x) && !inRemovedFaceSlab(x);
277}
278
279bool OpenCuboidChannel3D::isOutside(const util::Point &x) const { return !isInside(x); }
280
281bool OpenCuboidChannel3D::isNear(const util::Point &x, const double &tol) const {
282 return geom::isPointInsideBox(x, 3, box(tol));
283}
284
285bool OpenCuboidChannel3D::isNearBoundary(const util::Point &x, const double &tol,
286 const bool &within) const {
287 if (!isNear(x, within ? 0. : tol))
288 return false;
289 return isInside(x) && (isOutside(x + util::Point(tol, 0., 0.)) ||
290 isOutside(x - util::Point(tol, 0., 0.)) ||
291 isOutside(x + util::Point(0., tol, 0.)) ||
292 isOutside(x - util::Point(0., tol, 0.)) ||
293 isOutside(x + util::Point(0., 0., tol)) ||
294 isOutside(x - util::Point(0., 0., tol)));
295}
296
298 return isNearBoundary(x, 1.0e-8, false);
299}
300
301bool OpenCuboidChannel3D::isInside(const std::pair<util::Point, util::Point> &bx) const {
302 for (auto p : geom::getCornerPoints(3, bx))
303 if (!this->isInside(p))
304 return false;
305 return true;
306}
307
308bool OpenCuboidChannel3D::isOutside(const std::pair<util::Point, util::Point> &bx) const {
309 bool intersect = false;
310 for (auto p : geom::getCornerPoints(3, bx))
311 if (!intersect)
312 intersect = this->isInside(p);
313 return !intersect;
314}
315
316bool OpenCuboidChannel3D::isNear(const std::pair<util::Point, util::Point> &bx,
317 const double &tol) const {
318 return geom::areBoxesNear(this->box(), bx, tol, 3);
319}
320
321bool OpenCuboidChannel3D::doesIntersect(const std::pair<util::Point, util::Point> &bx) const {
322 for (auto p : geom::getCornerPoints(3, bx))
323 if (this->isInside(p))
324 return true;
325 return false;
326}
327
328std::string OpenCuboidChannel3D::printStr(int nt, int lvl) const {
329 auto tabS = util::io::getTabS(nt);
330 std::ostringstream oss;
331 oss << tabS << "------- OpenCuboidChannel3D (open shell) --------" << std::endl;
332 oss << tabS << "Outer AABB: [" << d_lo.d_x << "," << d_lo.d_y << "," << d_lo.d_z << "] — ["
333 << d_hi.d_x << "," << d_hi.d_y << "," << d_hi.d_z << "], t=" << d_t
334 << ", open_face=" << d_openFace << std::endl;
335 oss << tabS << "Center (d_x) = " << d_x.printStr() << std::endl;
336 if (lvl > 0)
337 oss << tabS << "volume = " << volume() << std::endl;
338 return oss.str();
339}
340
341} // namespace geom
Defines abstract geometrical domain.
std::vector< std::string > d_tags
Tags/attributes about the object.
Hollow axis-aligned cuboid shell with uniform wall thickness and one outer face open.
int d_openFace
Which outer face is open: 0=+x, 1=−x, 2=+y, 3=−y, 4=+z, 5=−z (world axes after transform).
bool inClosedShell(const util::Point &p) const
bool inRemovedFaceSlab(const util::Point &p) const
util::Point d_x
Centroid of the open shell (cached).
double volume() const override
Computes the volume (area in 2d, length in 1d) of object.
void transform(const util::Point &translation, const double &scale, const double &angle, const util::Point &axis, const util::Point *rotationPoint) override
Similarity about pivot (default: old center d_x), then rigid displacement = translation: ....
bool isNear(const util::Point &x, const double &tol) const override
Checks if point is within given distance of this object.
double inscribedRadius() const override
Computes the radius of biggest circle/sphere completely within the object.
bool isInside(const util::Point &x) const override
Checks if point is inside this object.
util::Point d_lo
Outer AABB low corner.
util::Point center() const override
Computes the center of object.
bool isOutside(const util::Point &x) const override
Checks if point is outside of this object.
bool isNearBoundary(const util::Point &x, const double &tol, const bool &within) const override
Checks if point is within given distance of this object.
bool doesIntersect(const util::Point &x) const override
Checks if point lies exactly on the boundary.
OpenCuboidChannel3D & operator=(const OpenCuboidChannel3D &other)
std::pair< util::Point, util::Point > box() const override
Computes the bounding box of object.
double boundingRadius() const override
Computes the radius of smallest circle/sphere such that object can be fit into it.
double d_t
Wall thickness.
std::string printStr(int nt=0, int lvl=0) const override
Returns the string containing printable information about the object.
util::Point d_hi
Outer AABB high corner.
void validateParams(double x0, double y0, double z0, double x1, double y1, double z1, double t, int open_face)
void aabbFromCorners(const util::Point *c, util::Point &lo, util::Point &hi)
void cornersFromAabb(const util::Point &lo, const util::Point &hi, util::Point *out8)
util::Point mapSimilarity(const util::Point &x, const util::Point &pivotDefault, const util::Point &t, double scale, double angle, const util::Point &axis, const util::Point *rotationPoint)
Definition geomObjects.h:55
bool isPointInsideBox(util::Point x, size_t dim, const std::pair< util::Point, util::Point > &box)
Returns true if point is inside box.
bool areBoxesNear(const std::pair< util::Point, util::Point > &b1, const std::pair< util::Point, util::Point > &b2, const double &tol, size_t dim)
Checks if given two boxes are within given distance from each other.
std::vector< util::Point > getCornerPoints(size_t dim, const std::pair< util::Point, util::Point > &box)
Returns all corner points in the box.
std::string getTabS(int nt)
Returns tab spaces of a given size.
Definition io.h:39
A structure to represent 3d vectors.
Definition point.h:30
double d_y
the y coordinate
Definition point.h:36
std::string printStr(int nt=0, int lvl=0) const
Returns the string containing printable information about the object.
Definition point.h:94
double d_z
the z coordinate
Definition point.h:39
double d_x
the x coordinate
Definition point.h:33