/* * Copyright 2020 Axel Waggershauser */ // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include namespace ZXing { template struct PointT { using value_t = T; T x = 0, y = 0; constexpr PointT() = default; constexpr PointT(T x, T y) : x(x), y(y) {} template constexpr explicit PointT(const PointT& p) : x(static_cast(p.x)), y(static_cast(p.y)) {} template PointT& operator+=(const PointT& b) { x += b.x; y += b.y; return *this; } }; template bool operator==(const PointT& a, const PointT& b) { return a.x == b.x && a.y == b.y; } template bool operator!=(const PointT& a, const PointT& b) { return !(a == b); } template auto operator-(const PointT& a) -> PointT { return {-a.x, -a.y}; } template auto operator+(const PointT& a, const PointT& b) -> PointT { return {a.x + b.x, a.y + b.y}; } template auto operator-(const PointT& a, const PointT& b) -> PointT { return {a.x - b.x, a.y - b.y}; } template auto operator*(const PointT& a, const PointT& b) -> PointT { return {a.x * b.x, a.y * b.y}; } template PointT operator*(U s, const PointT& a) { return {s * a.x, s * a.y}; } template PointT operator/(const PointT& a, U d) { return {a.x / d, a.y / d}; } template auto dot(const PointT& a, const PointT& b) -> decltype (a.x * b.x) { return a.x * b.x + a.y * b.y; } template auto cross(PointT a, PointT b) -> decltype(a.x * b.x) { return a.x * b.y - b.x * a.y; } /// L1 norm template T sumAbsComponent(PointT p) { return std::abs(p.x) + std::abs(p.y); } /// L2 norm template auto length(PointT p) -> decltype(std::sqrt(dot(p, p))) { return std::sqrt(dot(p, p)); } /// L-inf norm template T maxAbsComponent(PointT p) { return std::max(std::abs(p.x), std::abs(p.y)); } template auto distance(PointT a, PointT b) -> decltype(length(a - b)) { return length(a - b); } using PointI = PointT; using PointF = PointT; /// Calculate a floating point pixel coordinate representing the 'center' of the pixel. /// This is sort of the inverse operation of the PointI(PointF) conversion constructor. /// See also the documentation of the GridSampler API. inline PointF centered(PointI p) { return p + PointF(0.5f, 0.5f); } inline PointF centered(PointF p) { return {std::floor(p.x) + 0.5f, std::floor(p.y) + 0.5f}; } template PointF normalized(PointT d) { return PointF(d) / length(PointF(d)); } template PointT bresenhamDirection(PointT d) { return d / maxAbsComponent(d); } template PointT mainDirection(PointT d) { return std::abs(d.x) > std::abs(d.y) ? PointT(d.x, 0) : PointT(0, d.y); } } // ZXing