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
41template <typename PixelType>
42class CanonicalShapeTile : public ShapeTile<PixelType> {
43 public:
65 explicit CanonicalShapeTile(const ShapeTile<PixelType> &tile) : ShapeTile<PixelType>{}
66 {
67 // Helper struct to store candidate tiles with their flip flags
68 struct Candidate {
69 ShapeTile<PixelType> flipped_tile;
70 bool h_flip;
71 bool v_flip;
72
73 // Two-phase strict weak ordering: shape first, then full map as tiebreaker. The shape-only phase
74 // ensures non-symmetric shapes always select the geometrically minimal flip. The full-map fallback
75 // handles symmetric shapes (where all flip variants have identical key sets) by also considering
76 // color values. This guarantees that two tiles which are flips of each other with the same colors
77 // will converge on the same canonical form rather than each keeping their own color arrangement.
78 bool operator<(const Candidate &other) const
79 {
80 if (ShapeTile<PixelType>::compare_shape_only(flipped_tile, other.flipped_tile)) {
81 return true;
82 }
83 if (ShapeTile<PixelType>::compare_shape_only(other.flipped_tile, flipped_tile)) {
84 return false;
85 }
86 return flipped_tile < other.flipped_tile;
87 }
88 };
89
90 std::array flips = {
91 std::pair{false, false}, std::pair{false, true}, std::pair{true, false}, std::pair{true, true}};
92
93 std::vector<Candidate> candidates;
94 candidates.reserve(4);
95
96 for (const auto &[h, v] : flips) {
97 candidates.push_back({tile.flip(h, v), h, v});
98 }
99
100 auto min_candidate = *std::min_element(candidates.begin(), candidates.end());
101
102 // Assign the canonical tile data
103 *static_cast<ShapeTile<PixelType> *>(this) = min_candidate.flipped_tile;
104 h_flip_ = min_candidate.h_flip;
105 v_flip_ = min_candidate.v_flip;
106 }
107
122 auto operator<=>(const CanonicalShapeTile &other) const = default;
123
131 [[nodiscard]] bool h_flip() const
132 {
133 return h_flip_;
134 }
135
143 [[nodiscard]] bool v_flip() const
144 {
145 return v_flip_;
146 }
147
148 private:
149 bool h_flip_;
150 bool v_flip_;
151};
152
153} // 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.