24 using Mat3x3 = std::array<std::array<Fraction, 3>, 3>;
30 constexpr explicit Transform(Mat3x3 matrix) : matrix_{std::move(matrix)} {}
40 static constexpr auto identity() -> Transform {
41 const Fraction Z{0, 1}, O{1, 1};
42 return Transform{Mat3x3{{{{O, Z, Z}}, {{Z, O, Z}}, {{Z, Z, O}}}}};
55 static constexpr auto translation(std::int64_t tx, std::int64_t ty) -> Transform {
56 const Fraction Z{0, 1}, O{1, 1};
58 Mat3x3{{{{O, Z, Fraction{tx, 1}}}, {{Z, O, Fraction{ty, 1}}}, {{Z, Z, O}}}}};
75 static constexpr auto rotation(
const Fraction& angle_cos,
const Fraction& angle_sin)
77 const Fraction Z{0, 1};
78 return Transform{Mat3x3{{{{angle_cos, -angle_sin, Z}},
79 {{angle_sin, angle_cos, Z}},
80 {{Z, Z, Fraction{1, 1}}}}}};
97 static constexpr auto scaling(
const Fraction& sx,
const Fraction& sy) -> Transform {
98 const Fraction Z{0, 1};
99 return Transform{Mat3x3{{{{sx, Z, Z}}, {{Z, sy, Z}}, {{Z, Z, Fraction{1, 1}}}}}};
116 static constexpr auto shear(
const Fraction& shx,
const Fraction& shy) -> Transform {
117 const Fraction Z{0, 1}, O{1, 1};
118 return Transform{Mat3x3{{{{O, shx, Z}}, {{shy, O, Z}}, {{Z, Z, O}}}}};
130 constexpr auto compose(
const Transform& other)
const -> Transform {
132 for (
int i = 0; i < 3; ++i) {
133 for (
int j = 0; j < 3; ++j) {
135 for (
int k = 0; k < 3; ++k) {
136 sum = sum + matrix_[i][k] * other.matrix_[k][j];
141 return Transform{result};
151 constexpr auto apply_point(
const PgPoint& point)
const ->
PgPoint {
152 const Fraction x{point.
coord[0], 1};
153 const Fraction y{point.coord[1], 1};
154 const Fraction z{point.coord[2], 1};
156 const auto& m = matrix_;
157 const auto xn = m[0][0] * x + m[0][1] * y + m[0][2] * z;
158 const auto yn = m[1][0] * x + m[1][1] * y + m[1][2] * z;
159 const auto zn = m[2][0] * x + m[2][1] * y + m[2][2] * z;
162 {xn.numer() / xn.denom(), yn.numer() / yn.denom(), zn.numer() / zn.denom()}};
172 constexpr auto apply_line(
const PgLine& line)
const ->
PgLine {
173 const auto inv = inverse();
174 const Fraction x{line.coord[0], 1};
175 const Fraction y{line.coord[1], 1};
176 const Fraction z{line.coord[2], 1};
178 const auto& m = inv.matrix_;
179 const auto xn = m[0][0] * x + m[1][0] * y + m[2][0] * z;
180 const auto yn = m[0][1] * x + m[1][1] * y + m[2][1] * z;
181 const auto zn = m[0][2] * x + m[1][2] * y + m[2][2] * z;
184 {xn.numer() / xn.denom(), yn.numer() / yn.denom(), zn.numer() / zn.denom()}};
194 constexpr auto inverse() const -> Transform {
195 const auto& m = matrix_;
196 const auto& a = m[0][0];
197 const auto& b = m[0][1];
198 const auto& c = m[0][2];
199 const auto& d = m[1][0];
200 const auto& e = m[1][1];
201 const auto& f = m[1][2];
202 const auto& g = m[2][0];
203 const auto& h = m[2][1];
204 const auto& i_ = m[2][2];
206 const auto det = a * (e * i_ - f * h) - b * (d * i_ - f * g) + c * (d * h - e * g);
207 if (det == Fraction{0, 1}) {
208 throw std::domain_error{
"Cannot invert singular transformation matrix"};
210 const auto inv_det = Fraction{1, 1} / det;
214 {inv_det * (e * i_ - f * h), inv_det * (c * h - b * i_),
215 inv_det * (b * f - c * e)},
216 {inv_det * (f * g - d * i_), inv_det * (a * i_ - c * g),
217 inv_det * (c * d - a * f)},
218 {inv_det * (d * h - e * g), inv_det * (b * g - a * h),
219 inv_det * (a * e - b * d)},
224 constexpr auto matrix() const -> const Mat3x3& {
return matrix_; }
226 constexpr auto operator==(
const Transform& other)
const->bool {
227 return matrix_ == other.matrix_;
230 constexpr auto operator!=(
const Transform& other)
const->bool {
231 return !(*
this == other);
247 inline constexpr auto rotate_point(
const PgPoint& point,
const Fraction& angle_cos,
248 const Fraction& angle_sin) ->
PgPoint {
249 return Transform::rotation(angle_cos, angle_sin).apply_point(point);
259 inline constexpr auto translate_point(
const PgPoint& point, std::int64_t tx,
261 return Transform::translation(tx, ty).apply_point(point);
271 inline constexpr auto scale_point(
const PgPoint& point,
const Fraction& sx,
272 const Fraction& sy) ->
PgPoint {
273 return Transform::scaling(sx, sy).apply_point(point);
PG Line.
Definition pg_object.hpp:250
PG Point.
Definition pg_object.hpp:235
Definition ck_concepts.hpp:11
Core projective geometry object template (pg_object, PgObject, PgPoint, PgLine).
std::array< int64_t, 3 > coord
Definition pg_object.hpp:132