diff --git a/Makefile.am b/Makefile.am index a761b37f..56803449 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,6 +12,8 @@ SUBDIRS = test UTIL_FILES = \ backtrace.hpp \ + bezier.cpp \ + bezier.hpp \ bitwise.cpp \ bitwise.hpp \ colour.cpp \ diff --git a/bezier.cpp b/bezier.cpp new file mode 100644 index 00000000..407dfc91 --- /dev/null +++ b/bezier.cpp @@ -0,0 +1,124 @@ +/* + * This file is part of libgim. + * + * libgim is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * libgim is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with libgim. If not, see . + * + * Copyright 2015 Danny Robson + */ + +#include "bezier.hpp" + +#include "debug.hpp" + +#include +#include + + +//----------------------------------------------------------------------------- +template +util::bezier::bezier (const util::point2f _points[S]) +{ + std::copy (_points, _points + S, m_points); +} + + +//----------------------------------------------------------------------------- +namespace util { + template <> + point2f + bezier<2>::eval (float t) + { + CHECK_GE (t, 0); + CHECK_LE (t, 1); + + auto v0 = t * m_points[0]; + auto v1 = (1 - t) * m_points[1]; + + return { + v0.x + v1.x, + v0.y + v0.y + }; + } +} + + +//----------------------------------------------------------------------------- +namespace util { + template <> + point2f + bezier<3>::eval (float t) + { + CHECK_GE (t, 0); + CHECK_LE (t, 1); + + auto v0 = pow2 (1 - t) * m_points[0]; + auto v1 = 2 * (1 - t) * t * m_points[1]; + auto v2 = pow2 (t) * m_points[2]; + + return { + v0.x + v1.x + v2.x, + v0.y + v1.y + v2.y + }; + } +} + + +//----------------------------------------------------------------------------- +namespace util { + template <> + point2f + bezier<4>::eval (float t) + { + CHECK_GE (t, 0); + CHECK_LE (t, 1); + + auto v0 = pow (1 - t, 3) * m_points[0]; + auto v1 = 3 * pow2 (1 - t) * t * m_points[1]; + auto v2 = 3 * pow2 (1 - t) * t * m_points[2]; + auto v3 = pow (t, 3) * m_points[3]; + + return { + v0.x + v1.x + v2.x + v3.x, + v0.y + v1.y + v2.y + v3.y + }; + } +} + + +//----------------------------------------------------------------------------- +template +util::point2f& +util::bezier::operator[] (size_t idx) +{ + CHECK_LT (idx, S); + + return m_points[idx]; +} + + +//----------------------------------------------------------------------------- +template +const util::point2f& +util::bezier::operator[] (size_t idx) const +{ + CHECK_LT (idx, S); + + return m_points[idx]; +} + + +//----------------------------------------------------------------------------- +template class util::bezier<2>; +template class util::bezier<3>; +template class util::bezier<4>; diff --git a/bezier.hpp b/bezier.hpp new file mode 100644 index 00000000..75bdef7d --- /dev/null +++ b/bezier.hpp @@ -0,0 +1,41 @@ +/* + * This file is part of libgim. + * + * libgim is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * libgim is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with libgim. If not, see . + * + * Copyright 2015 Danny Robson + */ + +#ifndef __UTIL_BEZIER_HPP +#define __UTIL_BEZIER_HPP + +#include "point.hpp" + +namespace util { + template + class bezier { + bezier (const util::point2f[S]); + + point2f eval (float t); + float distance (point2f); + + point2f& operator[] (size_t idx); + const point2f& operator[] (size_t idx) const; + + private: + point2f m_points[S]; + }; +} + +#endif