izzi
SVG SUBSET C++ API
Loading...
Searching...
No Matches
a60-svg-radial-fill-hexagon.h
Go to the documentation of this file.
1#include <vector>
2#include <tuple>
3#include <cmath>
4#include <numbers>
5#include <functional>
6#include <queue>
7#include <unordered_set>
8#include <iostream>
9
10#include "a60-svg.h"
11
12namespace svg {
13
14/**
15 write a c++ function that tessalates hexagons, named
16 generate_radial_hexagons_v3. The arguments are (const int n, const
17 double r, const point_2t origin, const bool centerfilledp = false)
18 where n is the number of hexagons total, r is the radius a hexagon
19 (all hexagons same size), point_2t is a tuple of (x,y) points, and
20 centerfilledp when true starts filling in the center and when false
21 leaves the center empty
22
23 the function returns a std::vector<points> of hexagon centerpoints.
24 */
25
26//using point_2t = std::tuple<double, double>;
27
28// Hash function for point_2t to use in unordered_set
29// Use a simple hash combining x and y coordinates
31{
32 std::size_t
33 operator()(const point_2t& p) const
34 {
35 auto [x, y] = p;
36 return std::hash<double>()(x) ^ (std::hash<double>()(y) << 1);
37 }
38};
39
40// Equality function for point_2t
42{
43 bool
44 operator()(const point_2t& a, const point_2t& b) const
45 {
46 // Compare with a small epsilon for floating point precision
47 auto [ax, ay] = a;
48 auto [bx, by] = b;
49 return std::abs(ax - bx) < 1e-9 && std::abs(ay - by) < 1e-9;
50 }
51};
52
53
54/// Compute set of points for a radial fill of hexograms centered at p.
56radiate_hexagon_honeycomb(const point_2t origin, const double r, const uint n,
57 const bool centerfilledp)
58{
59 vrange hexagons;
60 if (n == 0)
61 return hexagons;
62
63 auto [x, y] = origin;
64
65
66 // For hexagonal grid, compute the horizontal and vertical spacing.
67
68 // Width of hexagon (flat-to-flat)
69 const double hex_width = 2.0 * r;
70
71 // Height of hexagon (point-to-point)
72 const double hex_height = std::sqrt(3.0) * r;
73
74 // Direction vectors for the 6 neighbors in a hexagonal grid
75 const vrange directions =
76 {
77 { hex_width, 0.0 }, // Right
78 { hex_width / 2.0, hex_height }, // Up-right
79 { -hex_width / 2.0, hex_height }, // Up-left
80 { -hex_width, 0.0 }, // Left
81 { -hex_width / 2.0, -hex_height }, // Down-left
82 { hex_width / 2.0, -hex_height } // Down-right
83 };
84
85 // Use BFS to generate hexagons radially
86 std::queue<point_2t> q;
87 std::unordered_set<point_2t, PointHash, PointEqual> visited;
88
89 // Ring 0 is the center hexagon.
90 if (centerfilledp)
91 {
92 q.push(origin);
93 hexagons.push_back(origin);
94 }
95 visited.insert(origin);
96
97 // Ring 1 (6 hexagons around center)
98 for (uint i = 0; i < directions.size() && hexagons.size() < n; i++)
99 {
100 const auto& movement = directions[i];
101 auto [dx, dy] = movement;
102 point_2t neighbor = { x + dx, y + dy };
103 q.push(neighbor);
104 visited.insert(neighbor);
105 hexagons.push_back(neighbor);
106 }
107
108 // Generate hexagons until we reach n total
109 while (hexagons.size() < n && !q.empty())
110 {
111 point_2t current = q.front();
112 q.pop();
113
114 auto [current_x, current_y] = current;
115
116 // Explore all 6 neighbors
117 for (const auto& dir : directions)
118 {
119 auto [dx, dy] = dir;
120 point_2t neighbor = {current_x + dx, current_y + dy};
121
122 // Check if we haven't visited this point and haven't reached n yet
123 if (visited.find(neighbor) == visited.end()
124 && hexagons.size() < n)
125 {
126 visited.insert(neighbor);
127 hexagons.push_back(neighbor);
128 q.push(neighbor);
129 }
130 }
131 }
132
133 return hexagons;
134}
135
136
137/// Compute set of angles, given points for a radial fill of hexograms
138/// centered at p.
139/// @param degreesp return results in degrees, not radians (default).
140vspace
141get_honeycomb_angles(const point_2t origin, const vrange& hexagons,
142 const bool degreesp = true)
143{
144 vspace angles;
145 angles.reserve(hexagons.size());
146
147 auto [x, y] = origin;
148 for (const auto& center : hexagons)
149 {
150 auto [hex_x, hex_y] = center;
151 double dx = hex_x - x;
152 double dy = hex_y - y;
153 double angle = std::atan2(dy, dx);
154 if (degreesp)
155 angle = (180 * (angle / k::pi));
156 angles.push_back(angle);
157 }
158
159 return angles;
160}
161
162} // namespace svg
vrange radiate_hexagon_honeycomb(const point_2t origin, const double r, const uint n, const bool centerfilledp)
Compute set of points for a radial fill of hexograms centered at p.
std::vector< point_2t > vrange
Definition izzi-points.h:46
std::vector< space_type > vspace
Split range, so one dimension of (x,y) cartesian plane.
Definition izzi-points.h:41
unsigned int uint
Definition a60-svg.h:57
std::tuple< space_type, space_type > point_2t
Point (x,y) in 2D space, space_type defaults to double.
Definition izzi-points.h:22
vspace get_honeycomb_angles(const point_2t origin, const vrange &hexagons, const bool degreesp=true)
Compute set of angles, given points for a radial fill of hexograms centered at p.
bool operator()(const point_2t &a, const point_2t &b) const
std::size_t operator()(const point_2t &p) const