-
Notifications
You must be signed in to change notification settings - Fork 1
Add Point2D library #6
base: main
Are you sure you want to change the base?
Changes from 2 commits
a0cd1b8
3dafb64
f54f134
6e9a62a
f87e75d
43ca90f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
add_subdirectory(utility) | ||
add_subdirectory(geometry) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
robocin_cpp_library( | ||
NAME point2d | ||
HDRS point2d.h | ||
SRCS point2d.cpp | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
# geometry | ||
|
||
A collection of geometric classes. | ||
|
||
## Table of Contents | ||
|
||
- [Point2D](#point2d) | ||
|
||
<a name="point2d"></a> | ||
|
||
## [`Point2D`](point2d.h) | ||
|
||
The `Point2D` templated struct represents a 2-dimensional point (vector) in a Cartesian coordinate system. It provides | ||
various methods and operators for manipulating and performing calculations with 2d-points. | ||
|
||
### Member Types | ||
|
||
- `value_type`: The type of the point's coordinates. | ||
- `reference`: A reference to `value_type`. | ||
- `size_type`: An unsigned integer type used for size and indexing. | ||
- `iterator`: An iterator type for iterating over mutable `Point2D` objects. | ||
- `const_iterator`: An iterator type for iterating over const `Point2D` objects. | ||
- `reverse_iterator`: A reverse iterator type for reverse iteration over mutable `Point2D` objects. | ||
- `const_reverse_iterator`: A reverse iterator type for reverse iteration over const `Point2D` objects. | ||
|
||
### Constructors | ||
|
||
- `Point2D()`: Default constructor. Initializes the point with coordinates (0, 0). | ||
- `Point2D(const Point2D& point)`: Copy constructor. Creates a new point by copying the coordinates of another point. | ||
- `Point2D(Point2D&& point)`: Move constructor. Creates a new point by moving the coordinates of another point. | ||
- `Point2D(value_type x, value_type y)`: Constructor. Initializes the point with the specified coordinates. | ||
- `Point2D(const OtherStructPoint2D auto& point)`: Initializes the point with the coordinates (`point.x`, `point.y`). | ||
- `Point2D(const ClassPoint2D auto& point)`: Initializes the point with the coordinates (`point.x()`, `point.y()`). | ||
- `template <class U, class V> Point2D(const std::pair<U, V>& pair)`: Constructor. Initializes the point with the | ||
coordinates from a `std::pair`. | ||
|
||
### Static Constructors | ||
|
||
- `static Point2D origin()`: Returns a point representing the origin (0, 0). | ||
- `static Point2D fromPolar(value_type angle) requires(std::floating_point<value_type>)`: Creates a point from polar | ||
coordinates with the given angle. | ||
- `static Point2D fromPolar(value_type angle, value_type length) requires(std::floating_point<value_type>)`: Creates a | ||
point from polar coordinates with the given angle and length. | ||
|
||
### Validators | ||
|
||
- `bool isNull() const`: Checks if the point is null (coordinates are both zero). Returns `true` | ||
if the point is null, `false` otherwise. | ||
|
||
### Arithmetic-Assignment Operators | ||
|
||
- `Point2D& operator+=(const Point2D& other)`: Adds the coordinates of another point to this point and updates its | ||
value. Returns a reference to the modified point. | ||
- `Point2D& operator-=(const Point2D& other)`: Subtracts the coordinates of another point from this point and updates | ||
its value. Returns a reference to the modified point. | ||
- `Point2D& operator*=(value_type factor)`: Multiplies the coordinates of this point by a scalar factor and updates its | ||
value. Returns a reference to the modified point. | ||
- `Point2D& operator/=(value_type factor)`: Divides the coordinates of this point by a scalar factor and updates its | ||
value. Returns a reference to the modified point. | ||
|
||
### Arithmetic Operators | ||
|
||
- `Point2D operator+(const Point2D& other) const`: Addition operator that returns the sum of two points. | ||
- `Point2D operator-(const Point2D& other) const`: Subtraction operator that returns the difference between two points. | ||
- `Point2D operator*(value_type factor) const`: Multiplication operator that scales the point by a factor. | ||
- `Point2D operator/(value_type factor) const`: Division operator that scales the point by the inverse of a factor. | ||
|
||
### Arithmetic Friend Operators | ||
|
||
- `friend Point2D operator*(value_type factor, const Point2D& point)`: Friend operator that allows multiplication of a | ||
point by a factor in the reverse order. | ||
|
||
### Sign Operators | ||
|
||
- `Point2D operator+() const`: Unary plus operator that returns the point itself. | ||
- `Point2D operator-() const`: Unary minus operator that returns the negation of the point. | ||
|
||
### Comparison Operators | ||
|
||
- `bool operator==(const Point2D& other) const`: Equality operator that checks if two points are equal. | ||
- `auto operator<=>(const Point2D& other) const`: Three-way comparison operator that compares two points and returns | ||
their relative ordering. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are these operators sufficient to do sorting? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For sure! Three way comparisons are able to replace all relational comparators. |
||
|
||
### Swap | ||
|
||
- `void swap(Point2D& other) noexcept`: Swaps the contents of the current point with another point. | ||
|
||
### Geometry | ||
|
||
- `value_type dot(const Point2D& other) const`: Computes the dot product of the current point and another point. | ||
- `value_type cross(const Point2D& other) const`: Computes the cross product of the current point and another point. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dot and cross are common vectors operations. Some operations are specific for vector or point interpretation, hardly for both. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should I change here in the description only? Or implement Point / Vector separately? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just description I think. |
||
- `value_type manhattanLength() const`: Computes the Manhattan distance between the origin and the current point. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This a example of point only operation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I dont like that. So for manhattan that commonly a binary function, I have to do: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very well observed! Again, this was partly inspired by Perhaps keeping both is reasonable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. |
||
- `value_type lengthSquared() const`: Computes the square of the Euclidean length of the current point. | ||
- `auto length() const`: Computes the Euclidean length of the current point. | ||
- `auto norm() const`: Computes the Euclidean length of the current point. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A point doesn't have length. |
||
- `value_type distSquaredTo(const Point2D& other) const`: Computes the square of the Euclidean distance between the | ||
current point and another point. | ||
- `auto distTo(const Point2D& other) const`: Computes the Euclidean distance between the current point and another | ||
point. | ||
- `auto angle() const`: Computes the angle (in radians) between the positive x-axis and the vector from the origin to | ||
the current point. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [-Pi , +PI]? |
||
- `auto angleTo(const Point2D& other) const`: Computes the angle (in radians) between the vector from the origin to the | ||
current point and the vector from the origin to another point. | ||
joseviccruz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Rotations | ||
|
||
- `void rotateCW90() &`: Rotates the current point 90 degrees clockwise. | ||
- `Point2D rotatedCW90() &&`: Returns a new point obtained by rotating the current point 90 degrees clockwise. | ||
- `Point2D rotatedCW90() const&`: Returns a new point obtained by rotating a copy of the current point 90 degrees | ||
clockwise. | ||
|
||
|
||
- `void rotateCCW90() &`: Rotates the current point 90 degrees counterclockwise. | ||
- `Point2D rotatedCCW90() &&`: Returns a new point obtained by rotating the current point 90 degrees counterclockwise. | ||
- `Point2D rotatedCCW90() const&`: Returns a new point obtained by rotating a copy of the current point 90 degrees | ||
counterclockwise. | ||
|
||
|
||
- `void rotateCW(value_type t) &`: Rotates the current point clockwise by a specified angle `t` (in radians). | ||
- `Point2D rotatedCW(value_type t) &&`: Returns a new point obtained by rotating the current point clockwise by a | ||
specified angle `t` (in radians). | ||
- `Point2D rotatedCW(value_type t) const&`: Returns a new point obtained by rotating a copy of the current point | ||
clockwise by a specified angle `t` (in radians). | ||
|
||
|
||
- `void rotateCCW(value_type t) &`: Rotates the current point counterclockwise by a specified angle `t` (in radians). | ||
- `Point2D rotatedCCW(value_type t) &&`: Returns a new point obtained by rotating the current point counterclockwise by | ||
a specified angle `t` (in radians). | ||
- `Point2D rotatedCCW(value_type t) const&`: Returns a new point obtained by rotating a copy of the current point | ||
counterclockwise by a specified angle `t` (in radians). | ||
|
||
### Resizing and Normalization | ||
|
||
- `void resize(value_type t) &`: Resizes the current point by a factor `t`. | ||
- `Point2D resized(value_type t) &&`: Returns a new point obtained by resizing the current point by a factor `t`. | ||
- `Point2D resized(value_type t) const&`: Returns a new point obtained by resizing a copy of the current point by a | ||
factor `t`. | ||
|
||
|
||
- `void normalize() &`: Normalizes the current point to have unit length. | ||
|
||
> **Note:** The normalization differs for real and integer numbers, being equivalent to `resize(1)` for real numbers, | ||
> and the division of coordinates by their gcd for integer numbers. | ||
|
||
- `Point2D normalized() &&`: Returns a new point obtained by normalizing the current point to have unit length. | ||
- `Point2D normalized() const&`: Returns a new point obtained by normalizing a copy of the current point to have unit | ||
length. | ||
|
||
|
||
- `void axesNormalize() &`: Normalizes the current point to have coordinates of -1, 0, or 1. | ||
- `Point2D axesNormalized() &&`: Returns a new point obtained by normalizing the current point to have coordinates of | ||
-1, 0, or 1. | ||
- `Point2D axesNormalized() const&`: Returns a new point obtained by normalizing a copy of the current point to have | ||
coordinates of -1, 0, or 1. | ||
|
||
### Array-like | ||
|
||
- `static size_type size()`: Returns the size of the point (always 2). | ||
- `reference operator[](size_type pos)`: Provides access to the elements of the point using the subscript operator. | ||
- `value_type operator[](size_type pos) const`: Provides access to the elements of the point using the subscript | ||
operator. | ||
|
||
### Iterators | ||
|
||
The following iterator methods provide support for iterating over the elements of the point: | ||
|
||
- `iterator begin() noexcept`. | ||
- `const_iterator begin() const noexcept`. | ||
- `iterator end() noexcept`. | ||
- `const_iterator end() const noexcept`. | ||
- `reverse_iterator rbegin() noexcept`. | ||
- `const_reverse_iterator rbegin() const noexcept`. | ||
- `reverse_iterator rend() noexcept`. | ||
- `const_reverse_iterator rend() const noexcept`. | ||
- `const_iterator cbegin() const noexcept`. | ||
- `const_iterator cend() const noexcept`. | ||
- `const_reverse_iterator crbegin() const noexcept`. | ||
- `const_reverse_iterator crend() const noexcept`. | ||
|
||
### Input/Output Operators | ||
|
||
The following operators allow input and output of `Point2D` objects: | ||
|
||
- `std::istream& operator>>(std::istream& is, Point2D& point)`: Reads a `Point2D` object from an input stream. | ||
- `std::ostream& operator<<(std::ostream& os, const Point2D& point)`: Writes a `Point2D` object to an output stream. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// | ||
// Created by José Cruz <joseviccruz> on 24/02/23. | ||
// Copyright (c) 2023 RobôCIn. | ||
// | ||
|
||
#ifndef ROBOCIN_GEOMETRY_POINT2D_INTERNAL_H | ||
#define ROBOCIN_GEOMETRY_POINT2D_INTERNAL_H | ||
|
||
#include <type_traits> | ||
|
||
namespace robocin::point2d_internal { | ||
|
||
template <class PT> | ||
concept StructPoint = requires(PT point) { | ||
point.x; | ||
point.y; | ||
}; | ||
|
||
template <class PT> | ||
concept ClassPoint = requires(PT point) { | ||
point.x(); | ||
point.y(); | ||
}; | ||
|
||
template <class PT> | ||
class iterator { | ||
using point_type = PT; | ||
using point_pointer = point_type*; | ||
|
||
template <class T> | ||
using dependent_const_t = std::conditional_t<std::is_const_v<point_type>, const T, T>; | ||
|
||
public: | ||
// NOLINTNEXTLINE(readability-identifier-naming) | ||
using iterator_category = std::random_access_iterator_tag; | ||
using difference_type = std::ptrdiff_t; | ||
using value_type = dependent_const_t<typename point_type::value_type>; | ||
using pointer = value_type*; | ||
using reference = value_type&; | ||
|
||
// Constructors ---------------------------------------------------------------------------------- | ||
constexpr iterator() = default; | ||
constexpr iterator(const iterator&) = default; | ||
constexpr iterator(iterator&&) noexcept = default; | ||
constexpr iterator(point_pointer ptr, difference_type index) : ptr_(ptr), index_(index) {} | ||
|
||
// Assignment operators -------------------------------------------------------------------------- | ||
constexpr iterator& operator=(const iterator&) = default; | ||
constexpr iterator& operator=(iterator&&) noexcept = default; | ||
|
||
// Destructor ------------------------------------------------------------------------------------ | ||
constexpr ~iterator() = default; | ||
|
||
// Dereference operators ------------------------------------------------------------------------- | ||
constexpr reference operator*() const { | ||
switch (index_) { | ||
case 0: return ptr_->x; | ||
case 1: return ptr_->y; | ||
default: throw std::out_of_range("Point2D::iterator operator*: index out of range."); | ||
} | ||
} | ||
|
||
constexpr reference operator[](difference_type n) const { | ||
switch (index_ + n) { | ||
case 0: return ptr_->x; | ||
case 1: return ptr_->y; | ||
default: throw std::out_of_range("Point2D::iterator operator[]: index out of range."); | ||
} | ||
} | ||
|
||
// Arithmetic-assignment operators --------------------------------------------------------------- | ||
constexpr iterator& operator+=(difference_type n) { return index_ += n, *this; } | ||
constexpr iterator& operator-=(difference_type n) { return index_ -= n, *this; } | ||
|
||
// Arithmetic operators -------------------------------------------------------------------------- | ||
constexpr iterator operator+(difference_type n) const { return iterator(*this) += n; } | ||
constexpr iterator operator-(difference_type n) const { return iterator(*this) -= n; } | ||
|
||
constexpr difference_type operator-(const iterator& other) const { return index_ - other.index_; } | ||
|
||
// Arithmetic friend operator -------------------------------------------------------------------- | ||
friend constexpr iterator operator+(difference_type n, const iterator& it) { return it + n; } | ||
|
||
// Increment and decrement operators ------------------------------------------------------------- | ||
constexpr iterator& operator++() { return ++index_, *this; } | ||
constexpr iterator operator++(int) { // NOLINT(cert-dcl21-cpp) | ||
iterator result = *this; | ||
return ++index_, result; | ||
} | ||
|
||
constexpr iterator& operator--() { return --index_, *this; } | ||
constexpr iterator operator--(int) { // NOLINT(cert-dcl21-cpp) | ||
iterator result = *this; | ||
return --index_, result; | ||
} | ||
|
||
// Comparison operators -------------------------------------------------------------------------- | ||
inline constexpr bool operator==(const iterator& other) const = default; | ||
inline constexpr auto operator<=>(const iterator& other) const = default; | ||
|
||
private: | ||
point_pointer ptr_{nullptr}; | ||
difference_type index_{0}; | ||
}; | ||
|
||
} // namespace robocin::point2d_internal | ||
|
||
#endif // ROBOCIN_GEOMETRY_POINT2D_INTERNAL_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// | ||
// Created by José Cruz <joseviccruz> on 24/02/23. | ||
// Copyright (c) 2023 RobôCIn. | ||
// | ||
|
||
#include "robocin/geometry/point2d.h" | ||
|
||
namespace robocin { | ||
|
||
template struct Point2D<std::int16_t>; | ||
template struct Point2D<std::int32_t>; | ||
template struct Point2D<std::int64_t>; | ||
template struct Point2D<float>; | ||
template struct Point2D<double>; | ||
template struct Point2D<long double>; | ||
|
||
} // namespace robocin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
discard null word for this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was originally inspired on
QPointF::isNull
, but I agree that isOrigin looks better for this purpose...However, perhaps isNull is a common interface for other geometric representations such as
QRectF
,QVector3D
...wdyt?