Commits

vrld committed cbdcb2c

[bezier curve] add missing files

Comments (0)

Files changed (4)

src/modules/math/BezierCurve.cpp

+/**
+ * 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 <iostream>
+
+using namespace std;
+
+namespace
+{
+
+/**
+ * Subdivide Bezier polygon.
+ **/
+void subdivide(vector<love::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<love::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<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<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<Vector> BezierCurve::render(size_t accuracy) const
+{
+	vector<Vector> vertices(controlPoints);
+	subdivide(vertices, accuracy);
+	return vertices;
+}
+
+
+} // namespace math
+} // namespace love

src/modules/math/BezierCurve.h

+/**
+ * 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 <vector>
+
+namespace love
+{
+namespace math
+{
+
+class BezierCurve : public Object
+{
+public:
+
+	/**
+	 * @param controlPoints Control polygon of the curve.
+	 **/
+	BezierCurve(const std::vector<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<Vector> render(size_t accuracy = 4) const;
+
+private:
+	std::vector<Vector> controlPoints;
+};
+
+}
+}
+
+#endif

src/modules/math/wrap_BezierCurve.cpp

+/**
+ * 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 <cmath>
+
+namespace love
+{
+namespace math
+{
+
+BezierCurve *luax_checkbeziercurve(lua_State *L, int idx)
+{
+	return luax_checktype<BezierCurve>(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<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

src/modules/math/wrap_BezierCurve.h

+/**
+ * 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