Browse Source

Added BezierCurve:renderSegment

muddmaker 11 years ago
parent
commit
238656ecc1

+ 1 - 0
changes.txt

@@ -23,6 +23,7 @@ LOVE 0.9.2 [Baby Inspector]
   * Added love.window.toPixels and love.window.fromPixels.
   * Added love.window.setPosition and love.window.getPosition, and 'x' and 'y' fields to love.window.setMode and t.window in love.conf.
   * Added love.filesystem.isSymlink, love.filesystem.setSymlinksEnabled, and love.filesystem.areSymlinksEnabled.
+  * Added BezierCurve:renderSegment.
 
   * Deprecated SpriteBatch:bind and SpriteBatch:unbind.
   * Deprecated all uses of the name 'FSAA' in favor of 'MSAA'.

+ 34 - 0
src/modules/math/BezierCurve.cpp

@@ -183,6 +183,40 @@ vector<Vector> BezierCurve::render(size_t accuracy) const
 	return vertices;
 }
 
+vector<Vector> BezierCurve::renderSegment(double start, double end, size_t accuracy) const
+{
+	if (controlPoints.size() < 2)
+		throw Exception("Invalid Bezier curve: Not enough control points.");
+	vector<Vector> vertices(controlPoints);
+	subdivide(vertices, accuracy);
+	if (start > 0)
+	{
+		Vector startPoint = evaluate(start);
+		for (size_t i = 0; i < vertices.size(); ++i)
+		{
+			if ((double)i / vertices.size() > start)
+			{
+				vertices.erase(vertices.begin(), vertices.begin() + i - 1);
+				break;
+			}
+		}
+		vertices.insert(vertices.begin(), startPoint);
+	}
+	if (end < 1)
+	{
+		Vector endPoint = evaluate(end);
+		for (size_t i = vertices.size(); i > 0; --i)
+		{
+			if ((double)(i - 1) / vertices.size() < end)
+			{
+				vertices.erase(vertices.begin() + i, vertices.end());
+				break;
+			}
+		}
+		vertices.insert(vertices.end(), endPoint);
+	}
+	return vertices;
+}
 
 } // namespace math
 } // namespace love

+ 9 - 0
src/modules/math/BezierCurve.h

@@ -113,6 +113,15 @@ public:
 	 * @returns A polygon chain that approximates the bezier curve.
 	 **/
 	std::vector<Vector> render(size_t accuracy = 4) const;
+	
+	/**
+	 * Renders a segment of the curve by subdivision.
+	 * @param start The starting point (between 0 and 1) on the curve.
+	 * @param end The ending point on the curve.
+	 * @param accuracy The 'fineness' of the curve.
+	 * @returns A polygon chain that approximates the segment along the curve
+	 **/
+	std::vector<Vector> renderSegment(double start, double end, size_t accuracy = 4) const;
 
 private:
 	std::vector<Vector> controlPoints;

+ 23 - 0
src/modules/math/wrap_BezierCurve.cpp

@@ -165,6 +165,28 @@ int w_BezierCurve_render(lua_State *L)
 	return 1;
 }
 
+int w_BezierCurve_renderSegment(lua_State *L)
+{
+	BezierCurve *curve = luax_checkbeziercurve(L, 1);
+	double start = luaL_checknumber(L, 2);
+	double end = luaL_checknumber(L, 3);
+	int accuracy = luaL_optinteger(L, 4, 5);
+	
+	std::vector<Vector> points;
+	luax_catchexcept(L, [&](){ points = curve->renderSegment(start, end, 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+2);
+		lua_pushnumber(L, points[i].y);
+		lua_rawseti(L, -2, 2*i+2);
+	}
+	
+	return 1;
+}
+	
 static const luaL_Reg functions[] =
 {
 	{"getDegree", w_BezierCurve_getDegree},
@@ -178,6 +200,7 @@ static const luaL_Reg functions[] =
 	{"scale", w_BezierCurve_scale},
 	{"evaluate", w_BezierCurve_evaluate},
 	{"render", w_BezierCurve_render},
+	{"renderSegment", w_BezierCurve_renderSegment},
 	{ 0, 0 }
 };
 

+ 1 - 0
src/modules/math/wrap_BezierCurve.h

@@ -42,6 +42,7 @@ int w_BezierCurve_rotate(lua_State *L);
 int w_BezierCurve_scale(lua_State *L);
 int w_BezierCurve_evaluate(lua_State *L);
 int w_BezierCurve_render(lua_State *L);
+int w_BezierCurve_renderSegment(lua_State *L);
 extern "C" int luaopen_beziercurve(lua_State *L);
 
 } // math