File indexing completed on 2025-12-16 09:41:54
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <algorithm>
0012 #include <array>
0013 #include <cmath>
0014 #include <vector>
0015
0016 #include "defs.hpp"
0017
0018 namespace actsvg {
0019
0020
0021
0022
0023
0024
0025
0026
0027 namespace views {
0028
0029
0030 using contour = std::vector<point2>;
0031
0032
0033 struct scene {
0034
0035 point2 _camera = {0., 0.};
0036
0037 point2 _view = {0., -1.};
0038
0039 bool _strict = false;
0040
0041 std::array<std::array<scalar, 2>, 2> _range = {
0042 std::array<scalar, 2>{std::numeric_limits<scalar>::lowest(),
0043 std::numeric_limits<scalar>::max()},
0044 std::array<scalar, 2>{std::numeric_limits<scalar>::lowest(),
0045 std::numeric_limits<scalar>::max()}};
0046 };
0047
0048
0049 struct x_y {
0050
0051
0052 scene _scene = scene();
0053
0054
0055 std::array<std::string, 2> _axis_names = {"x", "y"};
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 template <typename point3_type>
0066 point2 point(const point3_type &point_) const {
0067 return point2{static_cast<scalar>(point_[0]),
0068 static_cast<scalar>(point_[1])};
0069 }
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 template <typename point3_container>
0082 contour path(const point3_container &vertices_) const {
0083 contour c;
0084 c.reserve(vertices_.size());
0085 for (const auto &v : vertices_) {
0086
0087 c.push_back(point(v));
0088 }
0089 return c;
0090 }
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102 template <typename point3_container>
0103 contour operator()(const point3_container &vertices_) const {
0104 return path(vertices_);
0105 }
0106 };
0107
0108
0109 struct z_r {
0110
0111
0112 scene _scene = scene();
0113
0114
0115 std::array<std::string, 2> _axis_names = {"z", "r"};
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125 template <typename point3_type>
0126 point2 point(const point3_type &point_) const {
0127 scalar r = std::sqrt(point_[0] * point_[0] + point_[1] * point_[1]);
0128 return point2{static_cast<scalar>(point_[2]), r};
0129 }
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 template <typename point3_container>
0141 contour path(const point3_container &vertices_) const {
0142
0143 contour c;
0144 c.reserve(vertices_.size());
0145 for (const auto &v : vertices_) {
0146 c.push_back(point(v));
0147 }
0148 return c;
0149 }
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 template <typename point3_container>
0162 contour operator()(const point3_container &vertices_) const {
0163 return path(vertices_);
0164 }
0165 };
0166
0167
0168 struct z_phi {
0169
0170
0171 scene _scene = scene();
0172
0173
0174 bool _protect_phi = true;
0175
0176
0177 std::array<std::string, 2> _axis_names = {"z", "phi"};
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187 template <typename point3_type>
0188 point2 point(const point3_type &point_) const {
0189 scalar phi = std::atan2(point_[1], point_[0]);
0190 return point2{static_cast<scalar>(point_[2]), phi};
0191 }
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203 template <typename point3_container>
0204 contour path(const point3_container &vertices_) const {
0205
0206
0207 contour c;
0208 c.reserve(vertices_.size());
0209 std::vector<scalar> phi_values;
0210 phi_values.reserve(vertices_.size());
0211
0212 for (const auto &v : vertices_) {
0213 auto p2 = point(v);
0214 phi_values.push_back(v[1u]);
0215 c.push_back(p2);
0216 }
0217
0218 if (_protect_phi) {
0219 auto min_phi =
0220 std::min_element(phi_values.begin(), phi_values.end());
0221 auto max_phi =
0222 std::max_element(phi_values.begin(), phi_values.end());
0223
0224 if ((*min_phi) < 0. and (*max_phi) > 0. and
0225 ((*max_phi) - (*min_phi)) > M_PI) {
0226 for (auto &cv : c) {
0227 if (cv[1] < 0.) {
0228 cv[1] += 2_scalar * pi;
0229 }
0230 }
0231 }
0232 }
0233 return c;
0234 }
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246 template <typename point3_container>
0247 contour operator()(const point3_container &vertices_) const {
0248 return path(vertices_);
0249 }
0250 };
0251
0252
0253 struct z_rphi {
0254
0255
0256 scene _scene = scene();
0257
0258
0259 scalar _fixed_r = std::numeric_limits<scalar>::quiet_NaN();
0260
0261
0262 std::array<std::string, 2> _axis_names = {"z", "r ยท phi"};
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272 template <typename point3_type>
0273 point2 point(const point3_type &point_) const {
0274 scalar r = _fixed_r;
0275 if (std::isnan(r)) {
0276 r = std::sqrt(point_[0] * point_[0] + point_[1] * point_[1]);
0277 }
0278 scalar phi = std::atan2(point_[1], point_[0]);
0279 return point2{static_cast<float>(point_[2]), r * phi};
0280 }
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291 template <typename point3_container>
0292 contour path(const point3_container &vertices_) const {
0293
0294 contour c;
0295 c.reserve(vertices_.size());
0296 for (const auto &v : vertices_) {
0297 c.push_back(point(v));
0298 }
0299 return c;
0300 }
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312 template <typename point3_container>
0313 contour operator()(const point3_container &vertices_) const {
0314 return path(vertices_);
0315 }
0316 };
0317
0318 }
0319
0320 }