@@ -8,6 +8,7 @@
#pragma once
#include <algorithm>
+#include <cmath>
#include <ostream>
#include <string>
@@ -49,6 +50,70 @@ static inline bool operator!=(const Point &lhs, const Point &rhs)
std::ostream &operator<<(std::ostream &out, const Point &p);
+struct PointF {
+ constexpr PointF()
+ : x(0), y(0)
+ {
+ }
+
+ constexpr PointF(double _x, double _y)
+ : x(_x), y(_y)
+ {
+ }
+
+ constexpr PointF operator-() const
+ {
+ return PointF{ -x, -y };
+ }
+
+ constexpr PointF operator-(const PointF &p) const
+ {
+ return PointF(x - p.x, y - p.y);
+ }
+
+ constexpr PointF operator+(const PointF &p) const
+ {
+ return PointF(x + p.x, y + p.y);
+ }
+
+ constexpr double operator%(const PointF &p) const
+ {
+ return x * p.x + y * p.y;
+ }
+
+ constexpr PointF operator*(double f) const
+ {
+ return PointF(x * f, y * f);
+ }
+
+ constexpr PointF operator/(double f) const
+ {
+ return PointF(x / f, y / f);
+ }
+
+ constexpr double len2() const
+ {
+ return x * x + y * y;
+ }
+
+ constexpr double len() const
+ {
+ return std::sqrt(len2());
+ }
+
+ const std::string toString() const;
+
+ double x, y;
+};
+
+bool operator==(const PointF &lhs, const PointF &rhs);
+static inline bool operator!=(const PointF &lhs, const PointF &rhs)
+{
+ return !(lhs == rhs);
+}
+
+std::ostream &operator<<(std::ostream &out, const PointF &p);
+
class Size
{
public:
@@ -21,7 +21,7 @@ namespace libcamera {
/**
* \class Point
- * \brief Describe a point in two-dimensional space
+ * \brief Describe a point in two-dimensional integer space
*
* The Point structure defines a point in two-dimensional space with integer
* precision. The coordinates of a Point may be negative as well as positive.
@@ -94,6 +94,127 @@ std::ostream &operator<<(std::ostream &out, const Point &p)
return out;
}
+/**
+ * \class PointF
+ * \brief Describe a point in two-dimensional real space
+ *
+ * The Point structure defines a point in two-dimensional space with double
+ * precision. The coordinates of a Point may be negative as well as positive.
+ *
+ * This class exists separately from Point to not require all users of the
+ * Point class to have to use template parameters to specify a type.
+ */
+
+/**
+ * \fn PointF::PointF()
+ * \copydoc libcamera::Point::Point
+ */
+
+/**
+ * \fn PointF::PointF(double _x, double _y)
+ * \brief Construct a PointF at given \a _x and \a _y values
+ * \param[in] _x The x-coordinate
+ * \param[in] _y The y-coordinate
+ */
+
+/**
+ * \var PointF::x
+ * \copydoc libcamera::Point::x
+ */
+
+/**
+ * \var PointF::y
+ * \copydoc libcamera::Point::y
+ */
+
+/**
+ * \fn constexpr PointF PointF::operator-() const
+ * \copydoc libcamera::Point::operator-
+ */
+
+/**
+ * \fn constexpr PointF PointF::operator-(PointF const &p) const
+ * \brief Subtract one point from another, as if they were vectors
+ * \param[in] p The other point
+ * \return The difference of p from this point
+ */
+
+/**
+ * \fn PointF::operator+()
+ * \brief Add two points together, as if they were vectors
+ * \param[in] p The other point
+ * \return The sum of the two points
+ */
+
+/**
+ * \fn PointF::operator%()
+ * \brief Compute the dot product, treating the points as vectors
+ * \param[in] p The other point
+ * \return The dot product of the two points
+ */
+
+/**
+ * \fn PointF::operator*()
+ * \brief Scale up the point, as if it were a vector
+ * \param[in] f The factor
+ * \return The scaled point
+ */
+
+/**
+ * \fn PointF::operator/()
+ * \brief Scale down the point, as if it were a vector
+ * \param[in] f The factor
+ * \return The scaled point
+ */
+
+/**
+ * \fn PointF::len2()
+ * \brief Get the squared length of the point, as if it were a vector
+ * \return The squared length of the point
+ */
+
+/**
+ * \fn PointF::len()
+ * \brief Get the length of the point, as if it were a vector
+ * \return The length of the point
+ */
+
+/**
+ * \copydoc Point::toString()
+ */
+const std::string PointF::toString() const
+{
+ std::stringstream ss;
+ ss << *this;
+
+ return ss.str();
+}
+
+/**
+ * \copydoc operator==(const Point &lhs, const Point &rhs)
+ */
+bool operator==(const PointF &lhs, const PointF &rhs)
+{
+ return lhs.x == rhs.x && lhs.y == rhs.y;
+}
+
+/**
+ * \fn bool operator!=(const Point &lhs, const Point &rhs)
+ * \copydoc libcamera::Point::operator!=
+ */
+
+/**
+ * \brief Insert a text representation of a PointF into an output stream
+ * \param[in] out The output stream
+ * \param[in] p The point
+ * \return The output stream \a out
+ */
+std::ostream &operator<<(std::ostream &out, const PointF &p)
+{
+ out << "(" << p.x << ", " << p.y << ")";
+ return out;
+}
+
/**
* \class Size
* \brief Describe a two-dimensional size
@@ -33,6 +33,53 @@ protected:
return true;
}
+ template<typename T, typename U, typename V>
+ bool compareF(const T &lhs, const U &rhs,
+ V (PointF::*op)(const U &) const,
+ const char *opName, V expect)
+ {
+ V result = (lhs.*op)(rhs);
+
+ if (result != expect) {
+ cout << lhs << opName << " " << rhs
+ << "test failed" << std::endl;
+ return false;
+ }
+
+ return true;
+ }
+
+ template<typename T, typename U, typename V>
+ bool compareFScale(const T &lhs, const U &rhs,
+ V (PointF::*op)(U) const,
+ const char *opName, V expect)
+ {
+ V result = (lhs.*op)(rhs);
+
+ if (result != expect) {
+ cout << lhs << opName << " " << rhs
+ << "test failed" << std::endl;
+ return false;
+ }
+
+ return true;
+ }
+
+ template<typename T>
+ bool compareFLen(const T &lhs, double (PointF::*op)() const,
+ const char *opName, double expect)
+ {
+ double result = (lhs.*op)();
+
+ if (result != expect) {
+ cout << lhs << opName
+ << "test failed" << std::endl;
+ return false;
+ }
+
+ return true;
+ }
+
int run()
{
/*
@@ -88,6 +135,314 @@ protected:
return TestFail;
}
+ /*
+ * PointF tests
+ */
+
+ /* Equality */
+ if (!compare(PointF(50.1, 100.1), PointF(50.1, 100.1), &operator==, "==", true))
+ return TestFail;
+
+ if (!compare(PointF(-50.1, 100.1), PointF(-50.1, 100.1), &operator==, "==", true))
+ return TestFail;
+
+ if (!compare(PointF(50.1, -100.1), PointF(50.1, -100.1), &operator==, "==", true))
+ return TestFail;
+
+ if (!compare(PointF(-50.1, -100.1), PointF(-50.1, -100.1), &operator==, "==", true))
+ return TestFail;
+
+ if (!compare(PointF(-50.1, -100.0), PointF(-50.1, -100), &operator==, "==", true))
+ return TestFail;
+
+ /* Inequality */
+ if (!compare(PointF(50.1, 100.1), PointF(50.1, 100.2), &operator!=, "!=", true))
+ return TestFail;
+
+ if (!compare(PointF(-50.1, 100.1), PointF(-50.1, 100.01), &operator!=, "!=", true))
+ return TestFail;
+
+ if (!compare(PointF(-50.1, 100.1), PointF(-50.1, 100.1), &operator!=, "!=", false))
+ return TestFail;
+
+ if (!compare(PointF(50.1, -100.1), PointF(50.2, -100.1), &operator!=, "!=", true))
+ return TestFail;
+
+ if (!compare(PointF(-50.1, -100.1), PointF(-50.01, -100.0), &operator!=, "!=", true))
+ return TestFail;
+
+ if (!compare(PointF(-50.1, 100.1), PointF(50.1, 100.1), &operator!=, "!=", true))
+ return TestFail;
+
+ if (!compare(PointF(50.1, -100.1), PointF(50.1, 100.1), &operator!=, "!=", true))
+ return TestFail;
+
+ if (!compare(PointF(-50.1, -100.1), PointF(-50.1, -100.1), &operator!=, "!=", false))
+ return TestFail;
+
+ /* Negation */
+ if (PointF(50.1, 100.1) != -PointF(-50.1, -100.1) ||
+ PointF(50.1, 100.1) == -PointF(50.1, -100.1) ||
+ PointF(50.1, 100.1) == -PointF(-50.1, 100.1)) {
+ cout << "PointF negation test failed" << endl;
+ return TestFail;
+ }
+
+ typedef PointF (PointF::*pointfOp)(const PointF &) const;
+ typedef double (PointF::*pointfDotProd)(const PointF &) const;
+ typedef PointF (PointF::*pointfScale)(double) const;
+ typedef double (PointF::*pointfLen)() const;
+
+ /* Subtraction */
+ if (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(50.1, 100.1),
+ static_cast<pointfOp>(&PointF::operator-), "-",
+ PointF(0, 0)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(-50.1, 100.1), PointF(-50.1, 100.1),
+ static_cast<pointfOp>(&PointF::operator-), "-",
+ PointF(0, 0)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(50.1, -100.1), PointF(50.1, -100.1),
+ static_cast<pointfOp>(&PointF::operator-), "-",
+ PointF(0, 0)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(-50.1, -100.1), PointF(-50.1, -100.1),
+ static_cast<pointfOp>(&PointF::operator-), "-",
+ PointF(0, 0)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(-50.1, 100.1),
+ static_cast<pointfOp>(&PointF::operator-), "-",
+ PointF(100.2, 0)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(50.1, -100.1),
+ static_cast<pointfOp>(&PointF::operator-), "-",
+ PointF(0, 200.2)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(-50.1, -100.1),
+ static_cast<pointfOp>(&PointF::operator-), "-",
+ PointF(100.2, 200.2)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(-50.1, 100.1), PointF(50.1, 100.1),
+ static_cast<pointfOp>(&PointF::operator-), "-",
+ PointF(-100.2, 0)))
+ return TestFail;
+
+ /* Addition */
+ if (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(50.1, 100.1),
+ static_cast<pointfOp>(&PointF::operator+), "+",
+ PointF(100.2, 200.2)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(-50.1, 100.1), PointF(-50.1, 100.1),
+ static_cast<pointfOp>(&PointF::operator+), "+",
+ PointF(-100.2, 200.2)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(50.1, -100.1), PointF(50.1, -100.1),
+ static_cast<pointfOp>(&PointF::operator+), "+",
+ PointF(100.2, -200.2)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(-50.1, -100), PointF(-50.1, -100.1),
+ static_cast<pointfOp>(&PointF::operator+), "+",
+ PointF(-100.2, -200.1)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(-50.1, 100.1),
+ static_cast<pointfOp>(&PointF::operator+), "+",
+ PointF(0, 200.2)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.0), PointF(50.1, -100.1),
+ static_cast<pointfOp>(&PointF::operator+), "+",
+ PointF(100.2, -0.09999999999999432)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(50.1, 100.1), PointF(-50.1, -100.1),
+ static_cast<pointfOp>(&PointF::operator+), "+",
+ PointF(0, 0)))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, PointF>(PointF(-50.1, 100.1), PointF(50.1, 100.1),
+ static_cast<pointfOp>(&PointF::operator+), "+",
+ PointF(0, 200.2)))
+ return TestFail;
+
+ /* Dot product */
+ if (!compareF<PointF, PointF, double>(PointF(50.1, 100.1), PointF(50.1, 100.1),
+ static_cast<pointfDotProd>(&PointF::operator%), "%",
+ 12530.019999999999))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, double>(PointF(50.1, 100.1), PointF(50.1, -100.1),
+ static_cast<pointfDotProd>(&PointF::operator%), "%",
+ -7509.999999999998))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, double>(PointF(50.1, 100.1), PointF(-50.1, 100.1),
+ static_cast<pointfDotProd>(&PointF::operator%), "%",
+ 7509.999999999998))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, double>(PointF(50.1, 100.1), PointF(-50.1, -100.1),
+ static_cast<pointfDotProd>(&PointF::operator%), "%",
+ -12530.019999999999))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, double>(PointF(-50.1, 100.1), PointF(-50.1, 100.1),
+ static_cast<pointfDotProd>(&PointF::operator%), "%",
+ 12530.019999999999))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, double>(PointF(50.1, -100.1), PointF(50.1, -100.1),
+ static_cast<pointfDotProd>(&PointF::operator%), "%",
+ 12530.019999999999))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, double>(PointF(-50.1, -100.1), PointF(-50.1, -100.1),
+ static_cast<pointfDotProd>(&PointF::operator%), "%",
+ 12530.019999999999))
+ return TestFail;
+
+ if (!compareF<PointF, PointF, double>(PointF(0, 0), PointF(0, 0),
+ static_cast<pointfDotProd>(&PointF::operator%), "%",
+ 0))
+ return TestFail;
+
+
+ /* Scaling up */
+ if (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 0,
+ static_cast<pointfScale>(&PointF::operator*), "*",
+ PointF(0, 0)))
+ return TestFail;
+
+ if (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 1,
+ static_cast<pointfScale>(&PointF::operator*), "*",
+ PointF(10.5, -100.1)))
+ return TestFail;
+
+ if (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 1.0,
+ static_cast<pointfScale>(&PointF::operator*), "*",
+ PointF(10.5, -100.1)))
+ return TestFail;
+
+ if (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), -4.2,
+ static_cast<pointfScale>(&PointF::operator*), "*",
+ PointF(-44.1, 420.42)))
+ return TestFail;
+
+ if (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 4.2,
+ static_cast<pointfScale>(&PointF::operator*), "*",
+ PointF(44.1, -420.42)))
+ return TestFail;
+
+ if (!compareFScale<PointF, double, PointF>(PointF(0, -100.1), 4.2,
+ static_cast<pointfScale>(&PointF::operator*), "*",
+ PointF(0, -420.42)))
+ return TestFail;
+
+ if (!compareFScale<PointF, double, PointF>(PointF(-50.1, -100.1), 4.2,
+ static_cast<pointfScale>(&PointF::operator*), "*",
+ PointF(-210.42000000000002, -420.42)))
+ return TestFail;
+
+ /* Scaling down */
+ if (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 1,
+ static_cast<pointfScale>(&PointF::operator/), "/",
+ PointF(10.5, -100.1)))
+ return TestFail;
+
+ if (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 1.0,
+ static_cast<pointfScale>(&PointF::operator/), "/",
+ PointF(10.5, -100.1)))
+ return TestFail;
+
+ if (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), -4.2,
+ static_cast<pointfScale>(&PointF::operator/), "/",
+ PointF(-2.5, 23.833333333333332)))
+ return TestFail;
+
+ if (!compareFScale<PointF, double, PointF>(PointF(10.5, -100.1), 4.2,
+ static_cast<pointfScale>(&PointF::operator/), "/",
+ PointF(2.5, -23.833333333333332)))
+ return TestFail;
+
+ if (!compareFScale<PointF, double, PointF>(PointF(0, -100.1), 4.2,
+ static_cast<pointfScale>(&PointF::operator/), "/",
+ PointF(0, -23.833333333333332)))
+ return TestFail;
+
+ if (!compareFScale<PointF, double, PointF>(PointF(-50.1, -100.1), 4.2,
+ static_cast<pointfScale>(&PointF::operator/), "/",
+ PointF(-11.928571428571429, -23.833333333333332)))
+ return TestFail;
+
+
+ /* Squared length */
+ if (!compareFLen<PointF>(PointF(0, 0),
+ static_cast<pointfLen>(&PointF::len2), "len2",
+ 0))
+ return TestFail;
+
+ if (!compareFLen<PointF>(PointF(10.4, 0),
+ static_cast<pointfLen>(&PointF::len2), "len2",
+ 108.16000000000001))
+ return TestFail;
+
+ if (!compareFLen<PointF>(PointF(10.4, 50.1),
+ static_cast<pointfLen>(&PointF::len2), "len2",
+ 2618.17))
+ return TestFail;
+
+ if (!compareFLen<PointF>(PointF(-10.4, 50.1),
+ static_cast<pointfLen>(&PointF::len2), "len2",
+ 2618.17))
+ return TestFail;
+
+ if (!compareFLen<PointF>(PointF(-10.4, -50.1),
+ static_cast<pointfLen>(&PointF::len2), "len2",
+ 2618.17))
+ return TestFail;
+
+ /* Length */
+ if (!compareFLen<PointF>(PointF(0, 0),
+ static_cast<pointfLen>(&PointF::len), "len",
+ 0))
+ return TestFail;
+
+ if (!compareFLen<PointF>(PointF(10.4, 0),
+ static_cast<pointfLen>(&PointF::len), "len",
+ 10.4))
+ return TestFail;
+
+ if (!compareFLen<PointF>(PointF(10.4, 50.1),
+ static_cast<pointfLen>(&PointF::len), "len",
+ 51.16805644149483))
+ return TestFail;
+
+ if (!compareFLen<PointF>(PointF(-10.4, 50.1),
+ static_cast<pointfLen>(&PointF::len), "len",
+ 51.16805644149483))
+ return TestFail;
+
+ if (!compareFLen<PointF>(PointF(-10.4, -50.1),
+ static_cast<pointfLen>(&PointF::len), "len",
+ 51.16805644149483))
+ return TestFail;
+
+ /* Default constructor */
+ if (PointF() != PointF(0, 0)) {
+ cout << "Default constructor test failed" << endl;
+ return TestFail;
+ }
+
/*
* Size tests
*/