Major updates, start orientation, start documentation.
This commit is contained in:
parent
2ecc14f46c
commit
0dc47cdbce
|
@ -2,3 +2,5 @@
|
||||||
/cmake-build-*/
|
/cmake-build-*/
|
||||||
/stage/
|
/stage/
|
||||||
/package/
|
/package/
|
||||||
|
/docs/html/
|
||||||
|
/docs/latex/
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "tools/googletest"]
|
||||||
|
path = extern/googletest
|
||||||
|
url = https://github.com/google/googletest
|
|
@ -4,7 +4,7 @@ cmake_policy(SET CMP0048 NEW)
|
||||||
|
|
||||||
## CONFIG
|
## CONFIG
|
||||||
|
|
||||||
project(wrnav VERSION 0.0.1 LANGUAGES CXX)
|
project(wrmath VERSION 0.0.1 LANGUAGES CXX)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
@ -16,14 +16,15 @@ add_compile_options(-fprofile-arcs -ftest-coverage)
|
||||||
add_link_options(-fprofile-arcs -ftest-coverage)
|
add_link_options(-fprofile-arcs -ftest-coverage)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(PkgConfig)
|
|
||||||
pkg_search_module(GTEST REQUIRED gtest_main)
|
|
||||||
|
|
||||||
include_directories(include)
|
include_directories(include)
|
||||||
|
|
||||||
|
file(GLOB_RECURSE ${PROJECT_NAME}_HEADERS include/**.h)
|
||||||
|
file(GLOB_RECURSE ${PROJECT_NAME}_SOURCES src/*.cc)
|
||||||
|
|
||||||
## BUILD
|
## BUILD
|
||||||
|
|
||||||
|
add_library(lib${PROJECT_NAME} ${${PROJECT_NAME}_SOURCES})
|
||||||
# add_library(LIBNAME
|
# add_library(LIBNAME
|
||||||
# SOURCES
|
# SOURCES
|
||||||
# )
|
# )
|
||||||
|
@ -44,11 +45,23 @@ install(DIRECTORY include/${PROJECT_NAME}
|
||||||
|
|
||||||
# From Modern CMake:
|
# From Modern CMake:
|
||||||
# https://cliutils.gitlab.io/modern-cmake/chapters/testing/googletest.html
|
# https://cliutils.gitlab.io/modern-cmake/chapters/testing/googletest.html
|
||||||
|
add_subdirectory("${PROJECT_SOURCE_DIR}/extern/googletest" "extern/googletest")
|
||||||
|
include_directories("${gtest_SOURCE_DIR}/include")
|
||||||
|
mark_as_advanced(
|
||||||
|
BUILD_GMOCK BUILD_GTEST BUILD_SHARED_LIBS
|
||||||
|
gmock_build_tests gtest_build_samples gtest_build_tests
|
||||||
|
gtest_disable_pthreads gtest_force_shared_crt gtest_hide_internal_symbols
|
||||||
|
)
|
||||||
|
set_target_properties(gtest PROPERTIES FOLDER extern)
|
||||||
|
set_target_properties(gtest_main PROPERTIES FOLDER extern)
|
||||||
|
set_target_properties(gmock PROPERTIES FOLDER extern)
|
||||||
|
set_target_properties(gmock_main PROPERTIES FOLDER extern)
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
set(TEST_EXECS)
|
set(TEST_EXECS)
|
||||||
macro(package_add_gtest TESTNAME)
|
macro(package_add_gtest TESTNAME)
|
||||||
add_executable(${TESTNAME} ${ARGN})
|
add_executable(${TESTNAME} ${ARGN})
|
||||||
target_link_libraries(${TESTNAME} ${GTEST_LDFLAGS})
|
target_link_libraries(${TESTNAME} gtest_main lib${PROJECT_NAME})
|
||||||
target_compile_options(${TESTNAME} PUBLIC ${GTEST_CFLAGS})
|
target_compile_options(${TESTNAME} PUBLIC ${GTEST_CFLAGS})
|
||||||
add_test(NAME ${TESTNAME} COMMAND ${TESTNAME})
|
add_test(NAME ${TESTNAME} COMMAND ${TESTNAME})
|
||||||
set_target_properties(${TESTNAME} PROPERTIES
|
set_target_properties(${TESTNAME} PROPERTIES
|
||||||
|
@ -57,7 +70,9 @@ macro(package_add_gtest TESTNAME)
|
||||||
list(APPEND TEST_EXECS ${TESTNAME})
|
list(APPEND TEST_EXECS ${TESTNAME})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
# define the tests
|
||||||
package_add_gtest(vector_test test/vector_test.cc)
|
package_add_gtest(vector_test test/vector_test.cc)
|
||||||
|
package_add_gtest(orientation_test test/orientation_test.cc)
|
||||||
|
|
||||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --verbose DEPENDS ${TEST_EXECS})
|
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --verbose DEPENDS ${TEST_EXECS})
|
||||||
|
|
||||||
|
@ -65,3 +80,7 @@ add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --verbose DEPENDS ${TEST_
|
||||||
## DEPLOY
|
## DEPLOY
|
||||||
|
|
||||||
include(CMakePack.txt)
|
include(CMakePack.txt)
|
||||||
|
|
||||||
|
|
||||||
|
## DOCUMENTATE
|
||||||
|
add_subdirectory ("docs")
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
find_package(Doxygen REQUIRED)
|
||||||
|
|
||||||
|
# Find all the public headers
|
||||||
|
get_target_property(WRMATH_PUBLIC_HEADER_DIR libwrmath INTERFACE_INCLUDE_DIRECTORIES)
|
||||||
|
file(GLOB_RECURSE WRMATH_PUBLIC_HEADERS ${WRMATH_PUBLIC_HEADER_DIR}/*.h)
|
||||||
|
|
||||||
|
#This will be the main output of our command
|
||||||
|
set(DOXYGEN_INDEX_FILE ${CMAKE_CURRENT_SOURCE_DIR}/html/index.html)
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT ${DOXYGEN_INDEX_FILE}
|
||||||
|
DEPENDS ${WRMATH_PUBLIC_HEADERS}
|
||||||
|
COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
MAIN_DEPENDENCY Doxyfile
|
||||||
|
COMMENT "Generating docs")
|
||||||
|
|
||||||
|
add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE})
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,2 @@
|
||||||
|
sphinx
|
||||||
|
breathe
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 4e29e48840e611ecbef33d10960d7480d2e9034a
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef __WRMATH_GEOM_H
|
||||||
|
#define __WRMATH_GEOM_H
|
||||||
|
|
||||||
|
#include <wrmath/geom/vector.h>
|
||||||
|
#include <wrmath/geom/orientation.h>
|
||||||
|
|
||||||
|
#endif // __WRMATH_GEOM_H
|
|
@ -0,0 +1,63 @@
|
||||||
|
//
|
||||||
|
// Created by kyle on 8/3/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __WRMATH_GEOM_ORIENTATION_H
|
||||||
|
#define __WRMATH_GEOM_ORIENTATION_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <wrmath/geom/vector.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace wr {
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
|
||||||
|
float RadiansToDegreesF(float rads);
|
||||||
|
double RadiansToDegreesD(double rads);
|
||||||
|
float DegreesToRadiansF(float degrees);
|
||||||
|
double DegreesToRadiansD(double degrees);
|
||||||
|
|
||||||
|
|
||||||
|
constexpr uint8_t Basis_i = 0;
|
||||||
|
constexpr uint8_t Basis_j = 1;
|
||||||
|
constexpr uint8_t Basis_k = 2;
|
||||||
|
|
||||||
|
|
||||||
|
static const Vector2d Basis2d[] = {
|
||||||
|
Vector2d{1, 0},
|
||||||
|
Vector2d{0, 1},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const Vector2f Basis2f[] = {
|
||||||
|
Vector2f{1, 0},
|
||||||
|
Vector2f{0, 1},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const Vector3d Basis3d[] = {
|
||||||
|
Vector3d{1, 0, 0},
|
||||||
|
Vector3d{0, 1, 0},
|
||||||
|
Vector3d{0, 0, 1},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const Vector3f Basis3f[] = {
|
||||||
|
Vector3f{1, 0, 0},
|
||||||
|
Vector3f{0, 1, 0},
|
||||||
|
Vector3f{0, 0, 1},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
float Heading2f(Vector2f vec);
|
||||||
|
double Heading2d(Vector2d vec);
|
||||||
|
float Heading3f(Vector3f vec);
|
||||||
|
double Heading3d(Vector3d vec);
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
} // namespace wr
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __WRMATH_ORIENTATION_H
|
|
@ -0,0 +1,363 @@
|
||||||
|
#ifndef __WRMATH_GEOM_VECTOR_H
|
||||||
|
#define __WRMATH_GEOM_VECTOR_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <ostream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <wrmath/util/math.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace wr {
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vector provides a standard interface for dimensionless fixed-size
|
||||||
|
* vectors. Once instantiated, they cannot be modified. Note that while
|
||||||
|
* the type is generic, it's intended to be used with floating-point
|
||||||
|
* types. They can be indexed like arrays, and they contain an epsilon
|
||||||
|
* value that defines a tolerance for equality.
|
||||||
|
*/
|
||||||
|
template <typename T, size_t N>
|
||||||
|
class Vector {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* The default constructor creates a zero vector for a given
|
||||||
|
* type and size.
|
||||||
|
*/
|
||||||
|
Vector() { wr::util::DefaultEpsilon(this->epsilon); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If given an initializer_list, the vector is created with
|
||||||
|
* those values. There must be exactly N elements in the list.
|
||||||
|
* @param ilst
|
||||||
|
*/
|
||||||
|
Vector(std::initializer_list<T> ilst)
|
||||||
|
{
|
||||||
|
assert(ilst.size() == N);
|
||||||
|
|
||||||
|
wr::util::DefaultEpsilon(this->epsilon);
|
||||||
|
std::copy(ilst.begin(), ilst.end(), this->arr.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Magnitude computes the length of the vector.
|
||||||
|
* @return The length of the vector.
|
||||||
|
*/
|
||||||
|
T magnitude() const {
|
||||||
|
T result = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < N; i++) {
|
||||||
|
result += (this->arr[i] * this->arr[i]);
|
||||||
|
}
|
||||||
|
return std::sqrt(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the tolerance for equality checks. At a minimum, this allows
|
||||||
|
* for systemic errors in floating math arithmetic.
|
||||||
|
*
|
||||||
|
* @param eps is the maximum difference between this vector and
|
||||||
|
* another.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
setEpsilon(T eps)
|
||||||
|
{
|
||||||
|
this->epsilon = eps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether this is a zero vector.
|
||||||
|
* @return true if the vector is zero.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
isZero() const
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < N; i++) {
|
||||||
|
if (!wr::util::WithinTolerance(this->arr[i], (T)0.0, this->epsilon)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain the unit vector for this vector.
|
||||||
|
* @return The unit vector
|
||||||
|
*/
|
||||||
|
Vector
|
||||||
|
unitVector() const
|
||||||
|
{
|
||||||
|
return *this / this->magnitude();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if this is a unit vector, e.g. if its length is 1.
|
||||||
|
* @return true if the vector is a unit vector.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
isUnitVector() const
|
||||||
|
{
|
||||||
|
return wr::util::WithinTolerance(this->magnitude(), (T)1.0, this->epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the angle between two other vectors.
|
||||||
|
* @param other Another vector.
|
||||||
|
* @return The angle in radians between the two vectors.
|
||||||
|
*/
|
||||||
|
T
|
||||||
|
angle(const Vector<T, N> &other) const
|
||||||
|
{
|
||||||
|
Vector<T, N> unitA = this->unitVector();
|
||||||
|
Vector<T, N> unitB = other.unitVector();
|
||||||
|
|
||||||
|
// Can't compute angles with a zero vector.
|
||||||
|
assert(!this->isZero());
|
||||||
|
assert(!other.isZero());
|
||||||
|
return std::acos(unitA * unitB);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether two vectors are parallel.
|
||||||
|
* @param other Another vector
|
||||||
|
* @return True if the angle between the vectors is zero.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
isParallel(const Vector<T, N> &other) const
|
||||||
|
{
|
||||||
|
if (this->isZero() || other.isZero()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
T angle = this->angle(other);
|
||||||
|
if (wr::util::WithinTolerance(angle, (T)0.0, this->epsilon)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if two vectors are orthogonal or perpendicular to each
|
||||||
|
* other.
|
||||||
|
* @param other Another vector
|
||||||
|
* @return True if the two vectors are orthogonal.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
isOrthogonal(const Vector<T, N> &other) const
|
||||||
|
{
|
||||||
|
if (this->isZero() || other.isZero()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wr::util::WithinTolerance(*this * other, (T)0.0, this->epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project this vector onto some basis vector.
|
||||||
|
* @param basis The basis vector to be projected onto.
|
||||||
|
* @return A vector that is the projection of this onto the basis
|
||||||
|
* vector.
|
||||||
|
*/
|
||||||
|
Vector
|
||||||
|
projectParallel(const Vector<T, N> &basis) const
|
||||||
|
{
|
||||||
|
Vector<T, N> unit_basis = basis.unitVector();
|
||||||
|
|
||||||
|
return unit_basis * (*this * unit_basis);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project this vector perpendicularly onto some basis vector.
|
||||||
|
* This is also called the rejection of the vector.
|
||||||
|
* @param basis The basis vector to be projected onto.
|
||||||
|
* @return A vector that is the orthogonal projection of this onto
|
||||||
|
* the basis vector.
|
||||||
|
*/
|
||||||
|
Vector
|
||||||
|
projectOrthogonal(const Vector<T, N> &basis)
|
||||||
|
{
|
||||||
|
Vector<T, N> spar = this->projectParallel(basis);
|
||||||
|
return *this - spar;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform vector addition with another vector.
|
||||||
|
* @param other The vector to be added.
|
||||||
|
* @return A new vector that is the result of adding this and the
|
||||||
|
* other vector.
|
||||||
|
*/
|
||||||
|
Vector operator+(const Vector<T, N> &other) const {
|
||||||
|
Vector<T, N> vec;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < N; i++) {
|
||||||
|
vec.arr[i] = this->arr[i] + other.arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform vector subtraction with another vector.
|
||||||
|
* @param other The vector to be subtracted from this vector.
|
||||||
|
* @return A new vector that is the result of subtracting the
|
||||||
|
* other vector from this one.
|
||||||
|
*/
|
||||||
|
Vector operator-(const Vector<T, N> &other) const {
|
||||||
|
Vector<T, N> vec;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < N; i++) {
|
||||||
|
vec.arr[i] = this->arr[i] - other.arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform scalar multiplication of this vector by some scale factor.
|
||||||
|
* @param k The scaling value.
|
||||||
|
* @return A new vector that is this vector scaled by k.
|
||||||
|
*/
|
||||||
|
Vector operator*(const T k) const {
|
||||||
|
Vector<T, N> vec;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < N; i++) {
|
||||||
|
vec.arr[i] = this->arr[i] * k;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform scalar division of this vector by some scale factor.
|
||||||
|
* @param k The scaling value
|
||||||
|
* @return A new vector that is this vector scaled by 1/k.
|
||||||
|
*/
|
||||||
|
Vector operator/(const T k) const {
|
||||||
|
Vector<T, N> vec;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < N; i++) {
|
||||||
|
vec.arr[i] = this->arr[i] / k;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the dot product between two vectors.
|
||||||
|
* @param other The other vector.
|
||||||
|
* @return A scalar value that is the dot product of the two vectors.
|
||||||
|
*/
|
||||||
|
T operator*(const Vector<T, N> &other) const {
|
||||||
|
T result = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < N; i++) {
|
||||||
|
result += (this->arr[i] * other.arr[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two vectors for equality.
|
||||||
|
* @param other The other vector.
|
||||||
|
* @return Return true if all the components of both vectors are
|
||||||
|
* within the tolerance value.
|
||||||
|
*/
|
||||||
|
bool operator==(const Vector<T, N> &other) const {
|
||||||
|
for (size_t i = 0; i<N; i++) {
|
||||||
|
if (!wr::util::WithinTolerance(this->arr[i], other.arr[i], this->epsilon)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two vectors for inequality.
|
||||||
|
* @param other The other vector.
|
||||||
|
* @return Return true if any of the components of both vectors are
|
||||||
|
* not within the tolerance value.
|
||||||
|
*/
|
||||||
|
bool operator!=(const Vector<T, N> &other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support array indexing into vector.
|
||||||
|
* @param i The component index.
|
||||||
|
* @return The value of the vector component at i.
|
||||||
|
*/
|
||||||
|
T operator[](size_t i) const {
|
||||||
|
return this->arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support outputting vectors in the form "<i, j, ...>".
|
||||||
|
* @param outs An output stream.
|
||||||
|
* @param vec The vector to be formatted.
|
||||||
|
* @return The output stream.
|
||||||
|
*/
|
||||||
|
friend std::ostream& operator<<(std::ostream& outs, const Vector<T, N>& vec) {
|
||||||
|
outs << "<";
|
||||||
|
for (size_t i = 0; i < N; i++) {
|
||||||
|
outs << vec.arr[i];
|
||||||
|
if (i < (N-1)) {
|
||||||
|
outs << ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outs << ">";
|
||||||
|
return outs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const size_t dim = N;
|
||||||
|
T epsilon;
|
||||||
|
std::array<T, N> arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A number of shorthand aliases for vectors are provided. They follow
|
||||||
|
* the form of VectorNt, where N is the dimension and t is the type.
|
||||||
|
* For example, a 2D float vector is Vector2f.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef Vector<float, 2> Vector2f;
|
||||||
|
typedef Vector<float, 3> Vector3f;
|
||||||
|
typedef Vector<float, 4> Vector4f;
|
||||||
|
|
||||||
|
typedef Vector<double, 2> Vector2d;
|
||||||
|
typedef Vector<double, 3> Vector3d;
|
||||||
|
typedef Vector<double, 4> Vector4d;
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
} // namespace wr
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __WRMATH_GEOM_VECTOR_H
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef __WRNAV_UTIL_MATH_H
|
#ifndef __WRMATH_UTIL_MATH_H
|
||||||
#define __WRNAV_UTIL_MATH_H
|
#define __WRMATH_UTIL_MATH_H
|
||||||
|
|
||||||
|
|
||||||
namespace wr {
|
namespace wr {
|
||||||
|
@ -10,14 +10,14 @@ const double Epsilon_double = 0.0001;
|
||||||
const float Epsilon_float = 0.0001;
|
const float Epsilon_float = 0.0001;
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
DefaultEpsilon(double &epsilon)
|
DefaultEpsilon(double &epsilon)
|
||||||
{
|
{
|
||||||
epsilon = Epsilon_double;
|
epsilon = Epsilon_double;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
DefaultEpsilon(float &epsilon)
|
DefaultEpsilon(float &epsilon)
|
||||||
{
|
{
|
||||||
epsilon = Epsilon_float;
|
epsilon = Epsilon_float;
|
||||||
|
@ -25,7 +25,7 @@ DefaultEpsilon(float &epsilon)
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T
|
static T
|
||||||
WithinTolerance(T a, T b, T epsilon)
|
WithinTolerance(T a, T b, T epsilon)
|
||||||
{
|
{
|
||||||
return std::abs(a - b) < epsilon;
|
return std::abs(a - b) < epsilon;
|
||||||
|
@ -36,4 +36,4 @@ WithinTolerance(T a, T b, T epsilon)
|
||||||
} // namespace wr
|
} // namespace wr
|
||||||
|
|
||||||
|
|
||||||
#endif // __WRNAV_UTIL_MATH_H
|
#endif // __WRMATH_UTIL_MATH_H
|
|
@ -1,180 +0,0 @@
|
||||||
#ifndef __WRNAV_GEOM_VECTOR_H
|
|
||||||
#define __WRNAV_GEOM_VECTOR_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <cassert>
|
|
||||||
#include <cmath>
|
|
||||||
#include <initializer_list>
|
|
||||||
#include <ostream>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <wrnav/util/math.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace wr {
|
|
||||||
namespace geom {
|
|
||||||
|
|
||||||
template <typename T, size_t N>
|
|
||||||
class Vector {
|
|
||||||
public:
|
|
||||||
Vector() { wr::util::DefaultEpsilon(this->epsilon); }
|
|
||||||
|
|
||||||
Vector(std::initializer_list<T> ilst)
|
|
||||||
{
|
|
||||||
assert(ilst.size() == N);
|
|
||||||
|
|
||||||
wr::util::DefaultEpsilon(this->epsilon);
|
|
||||||
std::copy(ilst.begin(), ilst.end(), this->arr.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
T magnitude() const {
|
|
||||||
T result = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N; i++) {
|
|
||||||
result += (this->arr[i] * this->arr[i]);
|
|
||||||
}
|
|
||||||
return std::sqrt(result);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
setEpsilon(T epsilon)
|
|
||||||
{
|
|
||||||
this->epsilon = epsilon;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
isZero() const
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < N; i++) {
|
|
||||||
if (!wr::util::WithinTolerance(this->arr[i], 0.0, this->epsilon)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Vector
|
|
||||||
unitVector() const
|
|
||||||
{
|
|
||||||
return *this / this->magnitude();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
T
|
|
||||||
angle(const Vector<T, N> &rhs) const
|
|
||||||
{
|
|
||||||
Vector<T, N> unitA = this->unitVector();
|
|
||||||
Vector<T, N> unitB = rhs.unitVector();
|
|
||||||
|
|
||||||
return std::acos(unitA * unitB);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Vector operator+(const Vector<T, N> &rhs) const {
|
|
||||||
Vector<T, N> vec;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N; i++) {
|
|
||||||
vec.arr[i] = this->arr[i] + rhs.arr[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Vector operator-(const Vector<T, N> &rhs) const {
|
|
||||||
Vector<T, N> vec;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N; i++) {
|
|
||||||
vec.arr[i] = this->arr[i] - rhs.arr[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Scalar multiplication.
|
|
||||||
Vector operator*(const T k) const {
|
|
||||||
Vector<T, N> vec;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N; i++) {
|
|
||||||
vec.arr[i] = this->arr[i] * k;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Scalar division.
|
|
||||||
Vector operator/(const T k) const {
|
|
||||||
Vector<T, N> vec;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N; i++) {
|
|
||||||
vec.arr[i] = this->arr[i] / k;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Dot product.
|
|
||||||
T operator*(const Vector<T, N> &rhs) const {
|
|
||||||
T result = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < N; i++) {
|
|
||||||
result += (this->arr[i] * rhs.arr[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool operator==(const Vector<T, N> &rhs) const {
|
|
||||||
for (size_t i = 0; i<N; i++) {
|
|
||||||
if (!wr::util::WithinTolerance(this->arr[i], rhs.arr[i], this->epsilon)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool operator!=(const Vector<T, N> &rhs) const {
|
|
||||||
return !(*this == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
friend std::ostream& operator<<(std::ostream& outs, const Vector<T, N>& vec) {
|
|
||||||
outs << "<";
|
|
||||||
for (size_t i = 0; i < N; i++) {
|
|
||||||
outs << vec.arr[i];
|
|
||||||
if (i < (N-1)) {
|
|
||||||
outs << ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
outs << ">";
|
|
||||||
return outs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const size_t dim = N;
|
|
||||||
T epsilon;
|
|
||||||
std::array<T, N> arr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef Vector<float, 3> Vector3f;
|
|
||||||
typedef Vector<float, 4> Vector4f;
|
|
||||||
typedef Vector<double, 3> Vector3d;
|
|
||||||
typedef Vector<double, 4> Vector4d;
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace geom
|
|
||||||
} // namespace wr
|
|
||||||
|
|
||||||
|
|
||||||
#endif // __WRNAV_GEOM_VECTOR_H
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
#include <cmath>
|
||||||
|
#include <wrmath/geom/orientation.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace wr {
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
RadiansToDegreesF(float rads)
|
||||||
|
{
|
||||||
|
return rads * (180.0 / M_PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
RadiansToDegreesD(double rads)
|
||||||
|
{
|
||||||
|
return rads * (180.0 / M_PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
DegreesToRadiansF(float degrees)
|
||||||
|
{
|
||||||
|
return degrees * M_PI / 180.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
DegreesToRadiansD(double degrees)
|
||||||
|
{return degrees * M_PI / 180.0;
|
||||||
|
return degrees * M_PI / 180.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
Heading2f(Vector2f vec)
|
||||||
|
{
|
||||||
|
return vec.angle(Basis2f[Basis_i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
Heading3f(Vector3f vec)
|
||||||
|
{
|
||||||
|
Vector2f vec2f {vec[0], vec[1]};
|
||||||
|
return Heading2f(vec2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
Heading2d(Vector2d vec)
|
||||||
|
{
|
||||||
|
return vec.angle(Basis2d[Basis_i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
Heading3d(Vector3d vec)
|
||||||
|
{
|
||||||
|
Vector2d vec2d {vec[0], vec[1]};
|
||||||
|
return Heading2d(vec2d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
} // namespace wr
|
|
@ -0,0 +1,46 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <wrmath/geom/vector.h>
|
||||||
|
#include <wrmath/geom/orientation.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace wr;
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Orientation2f, Heading)
|
||||||
|
{
|
||||||
|
geom::Vector2f a {2.0, 2.0};
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(geom::Heading2f(a), geom::DegreesToRadiansF(45));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Orientation3f, Heading)
|
||||||
|
{
|
||||||
|
geom::Vector3f a {2.0, 2.0, 2.0};
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(geom::Heading3f(a), geom::DegreesToRadiansF(45));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Orientation2d, Heading)
|
||||||
|
{
|
||||||
|
geom::Vector2d a {2.0, 2.0};
|
||||||
|
|
||||||
|
EXPECT_NEAR(geom::Heading2d(a), geom::DegreesToRadiansF(45), 0.000001);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Orientation3d, Heading)
|
||||||
|
{
|
||||||
|
geom::Vector3d a {2.0, 2.0, 2.0};
|
||||||
|
|
||||||
|
EXPECT_NEAR(geom::Heading3d(a), geom::DegreesToRadiansF(45), 0.000001);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
#include <iostream>
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <wrnav/geom/vector.h>
|
#include <wrmath/geom/vector.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace wr;
|
using namespace wr;
|
||||||
|
@ -82,6 +81,8 @@ TEST(Vector3FloatTests, UnitVector)
|
||||||
geom::Vector3f unit {0.6651669556972103, 0.7069150218815566, 0.24046636539587804};
|
geom::Vector3f unit {0.6651669556972103, 0.7069150218815566, 0.24046636539587804};
|
||||||
|
|
||||||
EXPECT_EQ(vec3.unitVector(), unit);
|
EXPECT_EQ(vec3.unitVector(), unit);
|
||||||
|
EXPECT_FALSE(vec3.isUnitVector());
|
||||||
|
EXPECT_TRUE(unit.isUnitVector());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,6 +97,37 @@ TEST(Vector3FloatTests, Angle)
|
||||||
EXPECT_NEAR(c.angle(d), 1.052, 0.001);
|
EXPECT_NEAR(c.angle(d), 1.052, 0.001);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Vector3FloatTests, ParallelOrthogonalVectors)
|
||||||
|
{
|
||||||
|
geom::Vector3f a {-2.029, 9.97, 4.172};
|
||||||
|
geom::Vector3f b {-9.231, -6.639, -7.245};
|
||||||
|
geom::Vector3f c {-2.328, -7.284, -1.214};
|
||||||
|
geom::Vector3f d {-1.821, 1.072, -2.94};
|
||||||
|
geom::Vector3f e {-2.0, 1.0, 3.0};
|
||||||
|
geom::Vector3f f {-6.0, 3.0, 9.0};
|
||||||
|
|
||||||
|
EXPECT_FALSE(a.isParallel(b));
|
||||||
|
EXPECT_FALSE(a.isOrthogonal(b));
|
||||||
|
|
||||||
|
EXPECT_FALSE(c.isParallel(d));
|
||||||
|
EXPECT_TRUE(c.isOrthogonal(d));
|
||||||
|
|
||||||
|
EXPECT_TRUE(e.isParallel(f));
|
||||||
|
EXPECT_FALSE(e.isOrthogonal(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Vector3FloatTests, Projections)
|
||||||
|
{
|
||||||
|
geom::Vector4f a {3.009, -6.172, 3.692, -2.510};
|
||||||
|
geom::Vector4f b {6.404, -9.144, 2.759, 8.718};
|
||||||
|
geom::Vector4f c {1.9685, -2.8108, 0.8481, 2.6798};
|
||||||
|
geom::Vector4f d {1.0405, -3.3612, 2.8439, -5.1898};
|
||||||
|
|
||||||
|
ASSERT_EQ(a.projectParallel(b), c);
|
||||||
|
ASSERT_EQ(a.projectOrthogonal(b), d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(Vector3DoubleTests, Magnitude)
|
TEST(Vector3DoubleTests, Magnitude)
|
||||||
{
|
{
|
||||||
|
@ -173,6 +205,8 @@ TEST(Vector3DoubleTests, UnitVector)
|
||||||
geom::Vector3d unit {0.6651669556972103, 0.7069150218815566, 0.24046636539587804};
|
geom::Vector3d unit {0.6651669556972103, 0.7069150218815566, 0.24046636539587804};
|
||||||
|
|
||||||
EXPECT_EQ(vec3.unitVector(), unit);
|
EXPECT_EQ(vec3.unitVector(), unit);
|
||||||
|
EXPECT_FALSE(vec3.isUnitVector());
|
||||||
|
EXPECT_TRUE(unit.isUnitVector());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -188,6 +222,38 @@ TEST(Vector3DoubleTests, Angle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Vector3DoubleTests, ParallelOrthogonalVectors)
|
||||||
|
{
|
||||||
|
geom::Vector3d a {-2.029, 9.97, 4.172};
|
||||||
|
geom::Vector3d b {-9.231, -6.639, -7.245};
|
||||||
|
geom::Vector3d c {-2.328, -7.284, -1.214};
|
||||||
|
geom::Vector3d d {-1.821, 1.072, -2.94};
|
||||||
|
geom::Vector3d e {-2.0, 1.0, 3.0};
|
||||||
|
geom::Vector3d f {-6.0, 3.0, 9.0};
|
||||||
|
|
||||||
|
EXPECT_FALSE(a.isParallel(b));
|
||||||
|
EXPECT_FALSE(a.isOrthogonal(b));
|
||||||
|
|
||||||
|
EXPECT_FALSE(c.isParallel(d));
|
||||||
|
EXPECT_TRUE(c.isOrthogonal(d));
|
||||||
|
|
||||||
|
EXPECT_TRUE(e.isParallel(f));
|
||||||
|
EXPECT_FALSE(e.isOrthogonal(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Vector3DoubleTests, Projections)
|
||||||
|
{
|
||||||
|
geom::Vector4d a {3.009, -6.172, 3.692, -2.510};
|
||||||
|
geom::Vector4d b {6.404, -9.144, 2.759, 8.718};
|
||||||
|
geom::Vector4d c {1.9685, -2.8108, 0.8481, 2.6798};
|
||||||
|
geom::Vector4d d {1.0405, -3.3612, 2.8439, -5.1898};
|
||||||
|
|
||||||
|
ASSERT_EQ(a.projectParallel(b), c);
|
||||||
|
ASSERT_EQ(a.projectOrthogonal(b), d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue