| #include <cmath> // sqrt() sin() cos() |
| #include <vector> // std::vector |
| #include <stdexcept> // std::domain_error() |
| |
| namespace { |
| bool inside_polygon_(double radius, int odd_diameter, double xp, double yp, |
| int polygon_num, double degree) { |
| double radian = degree * (M_PI / 180), add_radian = 2.0 * M_PI / polygon_num, |
| x1 = 0, y1 = 0, x2, y2, xa = -odd_diameter, xb = -odd_diameter; |
| |
| for (int ii = 0; ii <= polygon_num; |
| ++ii, radian += add_radian, x1 = x2, y1 = y2) { |
| |
| |
| |
| |
| |
| |
| x2 = -radius * cos(radian); |
| y2 = -radius * sin(radian); |
| |
| |
| if (ii <= 0) { |
| continue; |
| } |
| |
| |
| |
| if (!(((y1 <= yp) && (yp <= y2)) || ((y2 <= yp) && (yp <= y1)))) { |
| continue; |
| } |
| |
| |
| if (y2 == y1) { |
| if (((x1 <= xp) && (xp <= x2)) || ((x2 <= xp) && (xp <= x1))) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| |
| if (xa == -odd_diameter) { |
| |
| |
| xa = (yp - y1) * (x2 - x1) / (y2 - y1) + x1; |
| } else |
| |
| if (xb == -odd_diameter) { |
| xb = (yp - y1) * (x2 - x1) / (y2 - y1) + x1; |
| if (((xa <= xp) && (xp <= xb)) || ((xb <= xp) && (xp <= xa))) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| return false; |
| } |
| |
| |
| void attenuation_distribution_( |
| std::vector<std::vector<double>> &lens_matrix, |
| std::vector<int> &lens_offsets, std::vector<double *> &lens_starts, |
| std::vector<int> &lens_sizes, int &odd_diameter, |
| const double radius |
| , |
| const double curve |
| , |
| const int polygon_num |
| , |
| const double degree |
| ) { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| if (0.0 == curve) { |
| |
| throw std::domain_error("curve is zero"); |
| } |
| |
| |
| odd_diameter = static_cast<int>(ceil(radius * 2.0)); |
| |
| |
| if (odd_diameter <= 1) { |
| |
| throw std::domain_error("diameter is equal less than 1"); |
| } |
| |
| |
| if (0 == (odd_diameter % 2)) { |
| ++odd_diameter; |
| } |
| |
| |
| lens_matrix.resize(odd_diameter); |
| for (int yy = 0; yy < odd_diameter; ++yy) { |
| lens_matrix.at(yy).resize(odd_diameter); |
| } |
| lens_offsets.resize(odd_diameter); |
| lens_starts.resize(odd_diameter); |
| lens_sizes.resize(odd_diameter); |
| |
| |
| |
| |
| |
| |
| double yp = 0.5 - (odd_diameter / 2.0); |
| for (int yy = 0; yy < odd_diameter; ++yy, yp += 1.0) { |
| lens_offsets.at(yy) = -1; |
| lens_starts.at(yy) = 0; |
| lens_sizes.at(yy) = -1; |
| double xp = 0.5 - (odd_diameter / 2.0); |
| for (int xx = 0; xx < odd_diameter; ++xx, xp += 1.0) { |
| const double length = sqrt(xp * xp + yp * yp); |
| if ((length <= radius) && |
| ((polygon_num < 3) || |
| inside_polygon_(radius, odd_diameter, xp, yp, polygon_num, |
| degree))) { |
| |
| |
| |
| |
| double val = 1.0 - (length / radius); |
| |
| |
| |
| val = pow(val, 1.0 / curve); |
| |
| |
| lens_matrix.at(yy).at(xx) = val; |
| |
| |
| |
| if (lens_offsets.at(yy) < 0) { |
| |
| lens_offsets.at(yy) = xx; |
| lens_starts.at(yy) = &lens_matrix.at(yy).at(xx); |
| } |
| } else { |
| |
| |
| |
| lens_matrix.at(yy).at(xx) = 0.0; |
| |
| |
| |
| if ((0 <= lens_offsets.at(yy)) && (lens_sizes.at(yy) < 0)) { |
| |
| lens_sizes.at(yy) = xx - lens_offsets.at(yy); |
| } |
| } |
| } |
| |
| if ((0 <= lens_offsets.at(yy)) && (lens_sizes.at(yy) < 0)) { |
| lens_sizes.at(yy) = odd_diameter - lens_offsets.at(yy); |
| } |
| } |
| |
| |
| double total = 0.0; |
| for (unsigned int yy = 0; yy < lens_matrix.size(); ++yy) { |
| for (unsigned int xx = 0; xx < lens_matrix.at(yy).size(); ++xx) { |
| total += lens_matrix.at(yy).at(xx); |
| } |
| } |
| for (unsigned int yy = 0; yy < lens_matrix.size(); ++yy) { |
| for (unsigned int xx = 0; xx < lens_matrix.at(yy).size(); ++xx) { |
| lens_matrix.at(yy).at(xx) /= total; |
| } |
| } |
| |
| } |
| } |