A single C++ library for types and utilities shared across the various EduceLab projects.
- Compiler supporting C++17
- CMake 3.15+
# Get the source
git clone https://github.com/educelab/libcore.git
cd libcore/
# Build the library
cmake -S . -B build/ -DCMAKE_BUILD_TYPE=Release
cmake --build build/
Follow the build instructions above, then run the following command from the root of the source directory:
# Install the library to the system
cmake --install build/
Much of the functionality in this project is header-only and can be copied to your include directory without linkage.
Note that you may have to adjust the #include
directives for files which reference other headers in this project. The
following files can be installed in this way:
utils/Caching.hpp
utils/Iteration.hpp
utils/Math.hpp
utils/String.hpp
utils/Filesystem.hpp
- Requires:
utils/String.hpp
- Requires:
utils/Flags.hpp
utils/LinearAlgebra.hpp
- Requires:
utils/Math.hpp
MatrixType
andVectorType
which implement theMat
andVec
interfaces.
- Requires:
types/Signals.hpp
types/Vec.hpp
- Requires:
utils/Math.hpp
- Requires:
types/Mat.hpp
- Requires:
types/Vec.hpp
- Requires:
types/Color.hpp
- Requires:
types/Vec.hpp
- Requires:
types/Mesh.hpp
- Requires:
types/Vec.hpp
types/Color.hpp
- Requires:
Include the primary header to load all classes:
#include <educelab/core.hpp>
using namespace educelab;
#include <educelab/core/types/Vec.hpp>
Vec3f v0{1, 0, 0}, v1{0, 1, 0};
std::cout << v0 + v1 << "\n"; // "[1, 1, 0]"
std::cout << v0.cross(v1) << "\n"; // "[0, 0, 1]"
See examples/VecExample.cpp for more usage examples.
#include <educelab/core/types/Mat.hpp>
#include <educelab/core/types/Vec.hpp>
// Input point
Vec<float, 4> p{0, 0, 0, 1};
std::cout << p << "\n"; // [0, 0, 0, 1]
// Construct a translation matrix
auto M = Mat<4,4>::Eye();
M(0, 3) = 1.f;
M(1, 3) = 2.f;
M(2, 3) = 3.f;
std::cout << "\n" << M << "\n"; // [[1, 0, 0, 1]
// [0, 1, 0, 2]
// [0, 0, 1, 3]
// [0, 0, 0, 1]]
// Apply transform
p = translate * p;
std::cout << p << "\n"; // [1, 2, 3, 1]
See examples/MatExample.cpp for more usage examples.
#include <educelab/core/types/Image.hpp>
#include <educelab/core/types/Vec.hpp>
// Construct an image
Image image(600, 800, 3, Depth::F32);
// Fill image with a color gradient
for (const auto [y, x] : range2D(image.height(), image.width())) {
auto r = float(x) / float(image.width() - 1);
auto g = float(y) / float(image.height() - 1);
auto b = 0.25F;
image.at<Vec3f>(y, x) = {r, g, b};
}
See examples/ImageExample.cpp for more usage examples.
#include <educelab/core/utils/Iteration.hpp>
// Numerical ranges
for(const auto& i : range(4, 12, 2)) {
std::cout << i << " ";
}
std::cout << "\n"; // "4 6 8 10"
// Indexed ranges
for(const auto& [idx, val] : enumerate("The", "quick", "brown", "fox.")) {
std::cout << "[" << idx << "] " << val << " ";
}
std::cout << "\n"; // "[0] The [1] quick [2] brown [3] fox."
See examples/IterationExample.cpp for more usage examples.
#include <educelab/core/utils/String.hpp>
// Upper and lower case transformers
std::string upper{"The quick brown fox"};
to_lower(upper);
std::cout << upper << "\n"; // "the quick brown fox"
to_upper(upper);
std::cout << upper << "\n"; // "THE QUICK BROWN FOX"
// Trim operations
std::cout << trim_left(" left") << "\n"; // "left"
std::cout << trim_right("right ") << "\n"; // "right"
std::cout << trim(" center ") << "\n"; // "center"
// Conversion to numeric types
std::cout << to_numeric<int>("3.14") << "\n"; // 3
std::cout << to_numeric<float>("3.14") << "\n"; // 3.14
See examples/StringExample.cpp for more usage examples.å
The default to_numeric
implementation relies upon std::from_chars
.
However, many compilers do not provide implementations for this function for
floating point types. In these circumstances, you may fall back to a
std::sto*
-based to_numeric
implementation by adding the
EDUCE_CORE_NEED_TO_NUMERIC_FP
compiler definition. When using this project
with CMake, this definition will automatically be added when you link against
the educelab::core
target.
(v0.2.1 and later) If not linking against the target (i.e. when using the
library as header-only), you may alternatively check the result of the
EDUCE_CORE_NEED_TO_NUMERIC_FP
CMake cache variable and set the definition
manually in your own project.
# Import libcore
FetchContent_Declare(
libcore
GIT_REPOSITORY https://github.com/educelab/libcore.git
GIT_TAG v0.2.1
EXCLUDE_FROM_ALL
)
FetchContent_MakeAvailable(libcore)
# Add an executable which has access to the libcore headers
add_executable(foo foo.cpp)
target_include_directories(foo
PUBLIC
$<BUILD_INTERFACE:${libcore_SOURCE_DIR}/include>
)
# Conditionally add the to_numeric compiler definition
if(EDUCE_CORE_NEED_TO_NUMERIC_FP)
target_compile_definitions(foo PRIVATE EDUCE_CORE_NEED_TO_NUMERIC_FP)
endif()
#include <educelab/core/utils/Iteration.hpp>
#include <educelab/core/utils/Caching.hpp>
// Create cache
using Key = ObjectCache<>::key_type;
ObjectCache cache;
// Store 5 ints and floats
std::vector<Key> keys;
for (auto val : range(5)) {
keys.emplace_back(cache.insert(val));
keys.emplace_back(cache.insert(0.5f + val));
}
// Print cached values
for (const auto& k : keys) {
// Check that the key is still in the cache
if (not cache.contains(k)) {
continue;
}
// Get the value and cast to the correct type
auto val = cache.get(k);
if (val.type() == typeid(int)) {
std::cout << std::any_cast<int>(val) << " ";
}
else if (val.type() == typeid(float)) {
std::cout << std::any_cast<float>(val) << " ";
}
}
std::cout << "\n"; // 0 0.5 1 1.5 2 2.5 3 3.5 4 4.5
See examples/CachingExample.cpp for more usage examples.