29 constexpr double eps = 1.0e-12;
30 if (std::abs(blo.d_z - bli.d_z) > 1.0e-9 || std::abs(bhi.d_z - bhi_i.d_z) > 1.0e-9)
31 throw std::runtime_error(
"buildAnnulus2DInCurrentModel: inner and outer rectangles must lie in the same z plane.");
33 if (!(bli.d_x > blo.d_x + eps && bhi_i.d_x < bhi.d_x - eps && bli.d_y > blo.d_y + eps &&
34 bhi_i.d_y < bhi.d_y - eps))
35 throw std::runtime_error(
36 "buildAnnulus2DInCurrentModel: inner rectangle must be strictly inside the outer rectangle.");
40 constexpr double eps = 1.0e-10;
41 if ((outer.
d_x - inner.
d_x).lengthSq() > eps)
42 throw std::runtime_error(
43 "buildAnnulus2DInCurrentModel: circle annulus requires coincident centers (concentric circles).");
44 if (inner.
d_r <= 0. || outer.
d_r <= inner.
d_r)
45 throw std::runtime_error(
46 "buildAnnulus2DInCurrentModel: require 0 < r_inner < r_outer for circle − circle.");
50 constexpr double eps = 1.0e-10;
51 if ((outer.
d_x - inner.
d_x).lengthSq() > eps)
52 throw std::runtime_error(
53 "buildAnnulus2DInCurrentModel: ellipse annulus requires coincident centers.");
55 throw std::runtime_error(
56 "buildAnnulus2DInCurrentModel: ellipse annulus requires the same orientation θ.");
57 if (inner.
d_a <= 0. || inner.
d_b <= 0. || outer.
d_a <= inner.
d_a || outer.
d_b <= inner.
d_b)
58 throw std::runtime_error(
59 "buildAnnulus2DInCurrentModel: require 0 < a_in < a_out and 0 < b_in < b_out.");
64 const double rx = std::max(e.
d_a, e.
d_b);
65 const double ry = std::min(e.
d_a, e.
d_b);
72static int firstTagOfDim(
const std::vector<std::pair<int, int>> &ov,
int dim) {
73 for (
const auto &pr : ov)
88 const double r_mid = 0.5 * (outer.d_r + inner.d_r);
89 return {outer.
d_x.
d_x + r_mid, outer.d_x.d_y, outer.d_x.d_z};
95 const double a_mid = 0.5 * (outer.d_a + inner.d_a);
96 return {outer.
d_x.
d_x + a_mid * std::cos(outer.d_theta),
97 outer.d_x.d_y + a_mid * std::sin(outer.d_theta), outer.d_x.d_z};
103 const auto &bli = inner.d_vertices[0];
104 return {0.5 * (blo.d_x + bli.d_x), 0.5 * (blo.d_y + bli.d_y), blo.d_z};
113 if (surface_tag < 0) {
114 std::vector<std::pair<int, int>> ents;
115 gmsh::model::getEntities(ents, 2);
117 surface_tag = ents.back().second;
119 if (surface_tag < 0) {
120 std::ostringstream oss;
121 oss <<
"buildAnnulus2DInCurrentModel: boolean cut did not produce a surface (ov size = "
122 << ov.size() <<
").";
123 throw std::runtime_error(oss.str());
127 const int p = gmsh::model::occ::addPoint(c.
d_x, c.
d_y, c.
d_z, h);
128 gmsh::model::occ::synchronize();
129 gmsh::model::mesh::embed(0, {p}, 2, surface_tag);
130 gmsh::model::occ::synchronize();
138 const auto &lo = outer.d_vertices[0];
139 const int out_surf = gmsh::model::occ::addRectangle(lo.d_x, lo.d_y, lo.d_z, outer.d_Lx, outer.d_Ly);
140 gmsh::model::occ::synchronize();
142 const auto &li = inner.d_vertices[0];
144 gmsh::model::occ::addRectangle(li.d_x, li.d_y, li.d_z, inner.d_Lx, inner.d_Ly);
145 gmsh::model::occ::synchronize();
147 std::vector<std::pair<int, int>> ov;
148 std::vector<std::vector<std::pair<int, int>>> ovv;
149 gmsh::model::occ::cut({{2, out_surf}}, {{2, in_surf}}, ov, ovv, -1,
true,
true);
150 gmsh::model::occ::synchronize();
151 gmsh::model::occ::removeAllDuplicates();
152 gmsh::model::occ::synchronize();
162 const int out_surf =
addDiskOcc(outer.d_x.d_x, outer.d_x.d_y, outer.d_x.d_z,
163 outer.d_r, outer.d_r);
164 gmsh::model::occ::synchronize();
165 const int in_surf =
addDiskOcc(inner.d_x.d_x, inner.d_x.d_y, inner.d_x.d_z,
166 inner.d_r, inner.d_r);
167 gmsh::model::occ::synchronize();
169 std::vector<std::pair<int, int>> ov;
170 std::vector<std::vector<std::pair<int, int>>> ovv;
171 gmsh::model::occ::cut({{2, out_surf}}, {{2, in_surf}}, ov, ovv, -1,
true,
true);
172 gmsh::model::occ::synchronize();
173 gmsh::model::occ::removeAllDuplicates();
174 gmsh::model::occ::synchronize();
185 gmsh::model::occ::synchronize();
187 gmsh::model::occ::synchronize();
189 std::vector<std::pair<int, int>> ov;
190 std::vector<std::vector<std::pair<int, int>>> ovv;
191 gmsh::model::occ::cut({{2, out_surf}}, {{2, in_surf}}, ov, ovv, -1,
true,
true);
192 gmsh::model::occ::synchronize();
193 gmsh::model::occ::removeAllDuplicates();
194 gmsh::model::occ::synchronize();
204 throw std::runtime_error(
"buildAnnulus2DInCurrentModel: expected d_dim == 2.");
206 throw std::runtime_error(
"buildAnnulus2DInCurrentModel: null inner or outer geometry.");
209 buildRectangleAnnulus2D(a, h);
213 buildCircleAnnulus2D(a, h);
217 buildEllipseAnnulus2D(a, h);
221 throw std::runtime_error(
222 "buildAnnulus2DInCurrentModel: unsupported 2D pair (supported: rectangle−rectangle, "
223 "circle−circle, ellipse−ellipse).");
Defines annulus rectangle.
GeomObject * d_outObj_p
Outer object.
util::Point center() const override
Computes the center of object.
size_t d_dim
Dimension objects live in.
GeomObject * d_inObj_p
Inner object.
Filled ellipse in the plane z = center.d_z, semi-axes in the xy plane.
double d_a
Semi-axis along local x before rotation (in-plane)
double d_b
Semi-axis along local y before rotation (in-plane)
double d_theta
Counter-clockwise rotation about +z through the center (radians)
const std::string d_name
name of object
std::vector< util::Point > d_vertices
Vertices.
int addEllipseDiskOcc(const geom::Ellipse &e)
void finish2DCutEmbedSurface(const std::vector< std::pair< int, int > > &ov, const geom::AnnulusGeomObject &a, double h)
void assertEllipseAnnulusValid(const geom::Ellipse &outer, const geom::Ellipse &inner)
void assertCircleAnnulusValid(const geom::Circle &outer, const geom::Circle &inner)
void buildCircleAnnulus2D(const geom::AnnulusGeomObject &a, double h)
util::Point embedPointInAnnulus2D(const geom::AnnulusGeomObject &a)
void buildEllipseAnnulus2D(const geom::AnnulusGeomObject &a, double h)
void assertRectangleAnnulusValid(const geom::Rectangle &outer, const geom::Rectangle &inner)
static int firstTagOfDim(const std::vector< std::pair< int, int > > &ov, int dim)
void buildRectangleAnnulus2D(const geom::AnnulusGeomObject &a, double h)
int addDiskOcc(double xc, double yc, double zc, double rx, double ry, double theta=0.)
OCC disk compatible with older Gmsh (no zAxis/xAxis) and newer APIs.
void buildAnnulus2DInCurrentModel(const geom::AnnulusGeomObject &a, double h)
A structure to represent 3d vectors.
double d_y
the y coordinate
double d_z
the z coordinate
double d_x
the x coordinate