From aa4d96317fec028c2a377d10d7254e74215ab762 Mon Sep 17 00:00:00 2001 From: vrld Date: Sun, 12 May 2013 22:01:12 +0200 Subject: [PATCH] [bezier curve] add missing files --- src/modules/math/BezierCurve.cpp | 146 +++++++++++++++++++++++ src/modules/math/BezierCurve.h | 91 ++++++++++++++ src/modules/math/wrap_BezierCurve.cpp | 165 ++++++++++++++++++++++++++ src/modules/math/wrap_BezierCurve.h | 45 +++++++ 4 files changed, 447 insertions(+) create mode 100644 src/modules/math/BezierCurve.cpp create mode 100644 src/modules/math/BezierCurve.h create mode 100644 src/modules/math/wrap_BezierCurve.cpp create mode 100644 src/modules/math/wrap_BezierCurve.h diff --git a/src/modules/math/BezierCurve.cpp b/src/modules/math/BezierCurve.cpp new file mode 100644 index 000000000..6dfa69740 --- /dev/null +++ b/src/modules/math/BezierCurve.cpp @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2006-2013 LOVE Development Team + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + **/ + +// LOVE +#include "BezierCurve.h" +#include "common/Exception.h" + +#include + +using namespace std; + +namespace +{ + +/** + * Subdivide Bezier polygon. + **/ +void subdivide(vector &points, int k) +{ + if (k <= 0) + return; + + // subdivision using de casteljau - subdivided control polygons are + // on the 'edges' of the computation scheme, e.g: + // + // ------LEFT-------> + // b00 b10 b20 b30 + // b01 b11 b21 .--- + // b02 b12 .---' + // b03 .---'RIGHT + // <--' + // + // the subdivided control polygon is: + // b00, b10, b20, b30, b21, b12, b03 + vector left, right; + left.reserve(points.size()); + right.reserve(points.size()); + + for (size_t step = 1; step < points.size(); ++step) + { + left.push_back(points[0]); + right.push_back(points[points.size() - step]); + for (size_t i = 0; i < points.size() - step; ++i) + points[i] = (points[i] + points[i+1]) * .5; + } + left.push_back(points[0]); + right.push_back(points[0]); + + // recurse + subdivide(left, k-1); + subdivide(right, k-1); + + // merge (right is in reversed order) + points.resize(left.size() + right.size() - 1); + for (size_t i = 0; i < left.size(); ++i) + points[i] = left[i]; + for (size_t i = 1; i < right.size(); ++i) + points[i-1 + left.size()] = right[right.size() - i - 1]; +} + +} + +namespace love +{ +namespace math +{ + +BezierCurve::BezierCurve(const vector &pts) + : controlPoints(pts) +{ +} + +const Vector &BezierCurve::getControlPoint(int i) const +{ + if (i < 0) + i += controlPoints.size(); + + if (i < 0 || i >= controlPoints.size()) + throw Exception("Invalid control point index"); + + return controlPoints[i]; +} + +void BezierCurve::setControlPoint(int i, const Vector &point) +{ + if (i < 0) + i += controlPoints.size(); + + if (i < 0 || i >= controlPoints.size()) + throw Exception("Invalid control point index"); + + controlPoints[i] = point; +} + +void BezierCurve::insertControlPoint(const Vector &point, int pos) +{ + if (pos < 0) + pos += controlPoints.size() + 1; + + if (pos < 0 || pos > controlPoints.size()) + throw Exception("Invalid control point index"); + + controlPoints.insert(controlPoints.begin() + pos, point); +} + +Vector BezierCurve::eval(double t) const +{ + if (t < 0 || t > 1) + throw Exception("Invalid evaluation parameter: must be between 0 and 1"); + + // de casteljau + vector points(controlPoints); + for (size_t step = 1; step < controlPoints.size(); ++step) + for (size_t i = 0; i < controlPoints.size() - step; ++i) + points[i] = points[i] * (1-t) + points[i+1] * t; + + return points[0]; +} + +vector BezierCurve::render(size_t accuracy) const +{ + vector vertices(controlPoints); + subdivide(vertices, accuracy); + return vertices; +} + + +} // namespace math +} // namespace love diff --git a/src/modules/math/BezierCurve.h b/src/modules/math/BezierCurve.h new file mode 100644 index 000000000..6a2f0bd76 --- /dev/null +++ b/src/modules/math/BezierCurve.h @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2006-2013 LOVE Development Team + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + **/ + +#ifndef LOVE_MATH_BEZIER_CURVE_H +#define LOVE_MATH_BEZIER_CURVE_H + +// LOVE +#include "common/Object.h" +#include "common/Vector.h" +#include + +namespace love +{ +namespace math +{ + +class BezierCurve : public Object +{ +public: + + /** + * @param controlPoints Control polygon of the curve. + **/ + BezierCurve(const std::vector &controlPoints); + + /** + * @returns Degree of the curve + **/ + size_t getDegree() const + { + return controlPoints.size() - 1; + } + + /** + * @returns i'th control point. + **/ + const Vector &getControlPoint(int i) const; + + /** + * Sets the i'th control point. + * @param i Control point to change. + * @param point New control point. + **/ + void setControlPoint(int i, const Vector &point); + + /** + * Insert a new control point before the i'th control point. + * If i < 0, Lua string indexing rules apply. + * @param point Control point to insert. + * @param pos Position to insert. + **/ + void insertControlPoint(const Vector &point, int pos = -1); + + /** + * Evaluates the curve at time t. + * @param t Curve parameter, must satisfy 0 <= t <= 1. + **/ + Vector eval(double t) const; + + /** + * Renders the curve by subdivision. + * @param accuracy The 'fineness' of the curve. + * @returns A polygon chain that approximates the bezier curve. + **/ + std::vector render(size_t accuracy = 4) const; + +private: + std::vector controlPoints; +}; + +} +} + +#endif diff --git a/src/modules/math/wrap_BezierCurve.cpp b/src/modules/math/wrap_BezierCurve.cpp new file mode 100644 index 000000000..957a41780 --- /dev/null +++ b/src/modules/math/wrap_BezierCurve.cpp @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2006-2013 LOVE Development Team + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + **/ + +#include "common/Exception.h" +#include "wrap_BezierCurve.h" + +#include + +namespace love +{ +namespace math +{ + +BezierCurve *luax_checkbeziercurve(lua_State *L, int idx) +{ + return luax_checktype(L, idx, "BezierCurve", MATH_BEZIER_CURVE_T); +} + +int w_BezierCurve_getDegree(lua_State *L) +{ + BezierCurve *curve = luax_checkbeziercurve(L, 1); + lua_pushnumber(L, curve->getDegree()); + return 1; +} + +int w_BezierCurve_getControlPoint(lua_State *L) +{ + BezierCurve *curve = luax_checkbeziercurve(L, 1); + int idx = luaL_checkinteger(L, 2); + + if (idx > 0) // 1-indexing + idx--; + + try + { + Vector v = curve->getControlPoint(idx); + lua_pushnumber(L, v.x); + lua_pushnumber(L, v.y); + } + catch (Exception &e) + { + return luaL_error(L, e.what()); + } + + return 2; +} + +int w_BezierCurve_setControlPoint(lua_State *L) +{ + BezierCurve *curve = luax_checkbeziercurve(L, 1); + int idx = luaL_checkinteger(L, 2); + double vx = luaL_checknumber(L, 3); + double vy = luaL_checknumber(L, 4); + + if (idx > 0) // 1-indexing + idx--; + + try + { + curve->setControlPoint(idx, Vector(vx,vy)); + } + catch (Exception &e) + { + return luaL_error(L, e.what()); + } + + return 0; +} + +int w_BezierCurve_insertControlPoint(lua_State *L) +{ + BezierCurve *curve = luax_checkbeziercurve(L, 1); + double vx = luaL_checknumber(L, 2); + double vy = luaL_checknumber(L, 3); + int idx = luaL_optinteger(L, 4, -1); + + if (idx > 0) // 1-indexing + idx--; + + try + { + curve->insertControlPoint(Vector(vx,vy), idx); + } + catch (Exception &e) + { + return luaL_error(L, e.what()); + } + + return 0; +} + +int w_BezierCurve_eval(lua_State *L) +{ + BezierCurve *curve = luax_checkbeziercurve(L, 1); + double t = luaL_checknumber(L, 2); + + try + { + Vector v = curve->eval(t); + lua_pushnumber(L, v.x); + lua_pushnumber(L, v.y); + } + catch (Exception &e) + { + return luaL_error(L, e.what()); + } + + return 2; + +} + +int w_BezierCurve_render(lua_State *L) +{ + BezierCurve *curve = luax_checkbeziercurve(L, 1); + int accuracy = luaL_optinteger(L, 2, 5); + + std::vector points = curve->render(accuracy); + + lua_createtable(L, points.size()*2, 0); + for (size_t i = 0; i < points.size(); ++i) + { + lua_pushnumber(L, points[i].x); + lua_rawseti(L, -2, 2*i+1); + lua_pushnumber(L, points[i].y); + lua_rawseti(L, -2, 2*i+2); + } + + return 1; +} + +static const luaL_Reg functions[] = +{ + {"getDegree", w_BezierCurve_getDegree}, + {"getControlPoint", w_BezierCurve_getControlPoint}, + {"setControlPoint", w_BezierCurve_setControlPoint}, + {"insertControlPoint", w_BezierCurve_insertControlPoint}, + {"eval", w_BezierCurve_eval}, + {"render", w_BezierCurve_render}, + { 0, 0 } +}; + +extern "C" int luaopen_beziercurve(lua_State *L) +{ + return luax_register_type(L, "BezierCurve", functions); +} + +} // math +} // love diff --git a/src/modules/math/wrap_BezierCurve.h b/src/modules/math/wrap_BezierCurve.h new file mode 100644 index 000000000..e5347311f --- /dev/null +++ b/src/modules/math/wrap_BezierCurve.h @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2006-2013 LOVE Development Team + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + **/ + +#ifndef LOVE_MATH_WRAP_BEZIER_CURVE_H +#define LOVE_MATH_WRAP_BEZIER_CURVE_H + +// LOVE +#include "BezierCurve.h" +#include "common/runtime.h" + +namespace love +{ +namespace math +{ + +BezierCurve *luax_checkbeziercurve(lua_State *L, int idx); +int w_BezierCurve_getDegree(lua_State *L); +int w_BezierCurve_getControlPoint(lua_State *L); +int w_BezierCurve_setControlPoint(lua_State *L); +int w_BezierCurve_insertControlPoint(lua_State *L); +int w_BezierCurve_eval(lua_State *L); +int w_BezierCurve_render(lua_State *L); +extern "C" int luaopen_beziercurve(lua_State *L); + +} // math +} // love + +#endif // LOVE_MATH_WRAP_RANDOM_GENERATOR_H