Major updates, start orientation, start documentation.
This commit is contained in:
		
							parent
							
								
									2ecc14f46c
								
							
						
					
					
						commit
						0dc47cdbce
					
				|  | @ -2,3 +2,5 @@ | |||
| /cmake-build-*/ | ||||
| /stage/ | ||||
| /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 | ||||
| 
 | ||||
| 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_REQUIRED ON) | ||||
| 
 | ||||
|  | @ -16,14 +16,15 @@ add_compile_options(-fprofile-arcs -ftest-coverage) | |||
| add_link_options(-fprofile-arcs -ftest-coverage) | ||||
| endif() | ||||
| 
 | ||||
| find_package(PkgConfig) | ||||
| pkg_search_module(GTEST REQUIRED gtest_main) | ||||
| 
 | ||||
| include_directories(include) | ||||
| 
 | ||||
| file(GLOB_RECURSE ${PROJECT_NAME}_HEADERS include/**.h) | ||||
| file(GLOB_RECURSE ${PROJECT_NAME}_SOURCES src/*.cc) | ||||
| 
 | ||||
| ## BUILD | ||||
| 
 | ||||
| add_library(lib${PROJECT_NAME} ${${PROJECT_NAME}_SOURCES}) | ||||
| # add_library(LIBNAME | ||||
| #     SOURCES | ||||
| # ) | ||||
|  | @ -44,11 +45,23 @@ install(DIRECTORY include/${PROJECT_NAME} | |||
| 
 | ||||
| # From Modern CMake: | ||||
| # 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) | ||||
| set(TEST_EXECS) | ||||
| macro(package_add_gtest TESTNAME) | ||||
| 	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}) | ||||
| 	add_test(NAME ${TESTNAME} COMMAND ${TESTNAME}) | ||||
| 	set_target_properties(${TESTNAME} PROPERTIES | ||||
|  | @ -57,7 +70,9 @@ macro(package_add_gtest TESTNAME) | |||
| 	list(APPEND TEST_EXECS ${TESTNAME}) | ||||
| endmacro() | ||||
| 
 | ||||
| # define the tests | ||||
| 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}) | ||||
| 
 | ||||
|  | @ -65,3 +80,7 @@ add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --verbose DEPENDS ${TEST_ | |||
| ## DEPLOY | ||||
| 
 | ||||
| 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 | ||||
| #define __WRNAV_UTIL_MATH_H | ||||
| #ifndef __WRMATH_UTIL_MATH_H | ||||
| #define __WRMATH_UTIL_MATH_H | ||||
| 
 | ||||
| 
 | ||||
| namespace wr { | ||||
|  | @ -10,14 +10,14 @@ const double Epsilon_double = 0.0001; | |||
| const float  Epsilon_float = 0.0001; | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| static void | ||||
| DefaultEpsilon(double &epsilon) | ||||
| { | ||||
| 	epsilon = Epsilon_double; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| static void | ||||
| DefaultEpsilon(float &epsilon) | ||||
| { | ||||
| 	epsilon = Epsilon_float; | ||||
|  | @ -25,7 +25,7 @@ DefaultEpsilon(float &epsilon) | |||
| 
 | ||||
| 
 | ||||
| template <typename T> | ||||
| T | ||||
| static T | ||||
| WithinTolerance(T a, T b, T epsilon) | ||||
| { | ||||
| 	return std::abs(a - b) < epsilon; | ||||
|  | @ -36,4 +36,4 @@ WithinTolerance(T a, T b, T epsilon) | |||
| } // 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 <wrnav/geom/vector.h> | ||||
| #include <wrmath/geom/vector.h> | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace wr; | ||||
|  | @ -82,6 +81,8 @@ TEST(Vector3FloatTests, UnitVector) | |||
| 	geom::Vector3f	unit {0.6651669556972103, 0.7069150218815566, 0.24046636539587804}; | ||||
| 
 | ||||
| 	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); | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
|  | @ -173,6 +205,8 @@ TEST(Vector3DoubleTests, UnitVector) | |||
| 	geom::Vector3d	unit {0.6651669556972103, 0.7069150218815566, 0.24046636539587804}; | ||||
| 
 | ||||
| 	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 | ||||
| main(int argc, char **argv) | ||||
| { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue