Porytiles
Loading...
Searching...
No Matches
canonical_shape_tile.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <compare>
6#include <vector>
7
9
10namespace porytiles {
11
43template <typename PixelType>
44class CanonicalShapeTile : public ShapeTile<PixelType> {
45 public:
69 explicit CanonicalShapeTile(const ShapeTile<PixelType> &tile) : ShapeTile<PixelType>{}
70 {
71 // Helper struct to store candidate tiles with their flip flags
72 struct Candidate {
73 ShapeTile<PixelType> flipped_tile;
74 bool h_flip;
75 bool v_flip;
76
77 /*
78 * Two-phase strict weak ordering: shape first, then full map as tiebreaker. The shape-only phase
79 * ensures non-symmetric shapes always select the geometrically minimal flip. The full-map fallback
80 * handles symmetric shapes (where all flip variants have identical key sets) by also considering
81 * color values. This guarantees that two tiles which are flips of each other with the same colors
82 * will converge on the same canonical form rather than each keeping their own color arrangement.
83 */
84 bool operator<(const Candidate &other) const
85 {
86 if (ShapeTile<PixelType>::compare_shape_only(flipped_tile, other.flipped_tile)) {
87 return true;
88 }
89 if (ShapeTile<PixelType>::compare_shape_only(other.flipped_tile, flipped_tile)) {
90 return false;
91 }
92 return flipped_tile < other.flipped_tile;
93 }
94 };
95
96 std::array flips = {
97 std::pair{false, false}, std::pair{false, true}, std::pair{true, false}, std::pair{true, true}};
98
99 std::vector<Candidate> candidates;
100 candidates.reserve(4);
101
102 for (const auto &[h, v] : flips) {
103 candidates.push_back({tile.flip(h, v), h, v});
104 }
105
106 auto min_candidate = *std::min_element(candidates.begin(), candidates.end());
107
108 // Assign the canonical tile data
109 *static_cast<ShapeTile<PixelType> *>(this) = min_candidate.flipped_tile;
110 h_flip_ = min_candidate.h_flip;
111 v_flip_ = min_candidate.v_flip;
112 }
113
130 auto operator<=>(const CanonicalShapeTile &other) const = default;
131
141 [[nodiscard]] bool h_flip() const
142 {
143 return h_flip_;
144 }
145
155 [[nodiscard]] bool v_flip() const
156 {
157 return v_flip_;
158 }
159
160 private:
161 bool h_flip_;
162 bool v_flip_;
163};
164
165} // namespace porytiles
A ShapeTile representation that stores the canonical (lexicographically minimal) orientation among al...
bool h_flip() const
Returns the horizontal flip flag.
bool v_flip() const
Returns the vertical flip flag.
CanonicalShapeTile(const ShapeTile< PixelType > &tile)
Constructs a CanonicalShapeTile by finding the canonical orientation of the input tile.
auto operator<=>(const CanonicalShapeTile &other) const =default
Three-way comparison operator that compares all fields.
An 8x8 tile backed by mask-based storage that maps shape regions to pixel values.