From 238656ecc163a1c608e05c45d2a1f2e9f7d88977 Mon Sep 17 00:00:00 2001 From: muddmaker Date: Tue, 30 Sep 2014 17:36:10 -0700 Subject: [PATCH 1/6] Added BezierCurve:renderSegment --- changes.txt | 1 + src/modules/math/BezierCurve.cpp | 34 +++++++++++++++++++++++++++ src/modules/math/BezierCurve.h | 9 +++++++ src/modules/math/wrap_BezierCurve.cpp | 23 ++++++++++++++++++ src/modules/math/wrap_BezierCurve.h | 1 + 5 files changed, 68 insertions(+) diff --git a/changes.txt b/changes.txt index 41704b360..06a651fea 100644 --- a/changes.txt +++ b/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'. diff --git a/src/modules/math/BezierCurve.cpp b/src/modules/math/BezierCurve.cpp index 33c96c56f..7ceac9e7e 100644 --- a/src/modules/math/BezierCurve.cpp +++ b/src/modules/math/BezierCurve.cpp @@ -183,6 +183,40 @@ vector BezierCurve::render(size_t accuracy) const return vertices; } +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 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 diff --git a/src/modules/math/BezierCurve.h b/src/modules/math/BezierCurve.h index 9370dc52f..e35e45c08 100644 --- a/src/modules/math/BezierCurve.h +++ b/src/modules/math/BezierCurve.h @@ -113,6 +113,15 @@ public: * @returns A polygon chain that approximates the bezier curve. **/ std::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 renderSegment(double start, double end, size_t accuracy = 4) const; private: std::vector controlPoints; diff --git a/src/modules/math/wrap_BezierCurve.cpp b/src/modules/math/wrap_BezierCurve.cpp index 659c0bd7f..b49b4f231 100644 --- a/src/modules/math/wrap_BezierCurve.cpp +++ b/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 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 } }; diff --git a/src/modules/math/wrap_BezierCurve.h b/src/modules/math/wrap_BezierCurve.h index ad0558e96..9eb6fb9bf 100644 --- a/src/modules/math/wrap_BezierCurve.h +++ b/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 From ccd856255d78388e2a5124e6cb132246e7604706 Mon Sep 17 00:00:00 2001 From: muddmaker Date: Thu, 2 Oct 2014 18:22:54 -0700 Subject: [PATCH 2/6] fix last commit --- src/modules/math/BezierCurve.cpp | 39 ++++++++++++++------------- src/modules/math/wrap_BezierCurve.cpp | 2 +- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/modules/math/BezierCurve.cpp b/src/modules/math/BezierCurve.cpp index 7ceac9e7e..05e84e92f 100644 --- a/src/modules/math/BezierCurve.cpp +++ b/src/modules/math/BezierCurve.cpp @@ -189,31 +189,34 @@ vector BezierCurve::renderSegment(double start, double end, size_t accur throw Exception("Invalid Bezier curve: Not enough control points."); vector vertices(controlPoints); subdivide(vertices, accuracy); - if (start > 0) + if (start == end) { - 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); + vertices.clear(); } - if (end < 1) + else if (start < end) { - Vector endPoint = evaluate(end); - for (size_t i = vertices.size(); i > 0; --i) + if (start > 0 && start < 1) { - if ((double)(i - 1) / vertices.size() < end) + for (size_t i = 0; i < vertices.size(); ++i) { - vertices.erase(vertices.begin() + i, vertices.end()); - break; + if ((double)i / vertices.size() > start) + { + vertices.erase(vertices.begin(), vertices.begin() + i - 1); + break; + } + } + } + if (end < 1 && end > 0) + { + 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; } diff --git a/src/modules/math/wrap_BezierCurve.cpp b/src/modules/math/wrap_BezierCurve.cpp index b49b4f231..cd5b72db5 100644 --- a/src/modules/math/wrap_BezierCurve.cpp +++ b/src/modules/math/wrap_BezierCurve.cpp @@ -179,7 +179,7 @@ int w_BezierCurve_renderSegment(lua_State *L) for (size_t i = 0; i < points.size(); ++i) { lua_pushnumber(L, points[i].x); - lua_rawseti(L, -2, 2*i+2); + lua_rawseti(L, -2, 2*i+1); lua_pushnumber(L, points[i].y); lua_rawseti(L, -2, 2*i+2); } From 637908ab4366919efb20983813a84a25dc5a9bb6 Mon Sep 17 00:00:00 2001 From: muddmaker Date: Mon, 22 Dec 2014 14:50:44 -0800 Subject: [PATCH 3/6] Improve renderSegment --- src/modules/math/BezierCurve.cpp | 31 +++++++++---------------------- src/modules/math/BezierCurve.h | 2 ++ 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/modules/math/BezierCurve.cpp b/src/modules/math/BezierCurve.cpp index 05e84e92f..04a23c079 100644 --- a/src/modules/math/BezierCurve.cpp +++ b/src/modules/math/BezierCurve.cpp @@ -195,28 +195,15 @@ vector BezierCurve::renderSegment(double start, double end, size_t accur } else if (start < end) { - if (start > 0 && start < 1) - { - for (size_t i = 0; i < vertices.size(); ++i) - { - if ((double)i / vertices.size() > start) - { - vertices.erase(vertices.begin(), vertices.begin() + i - 1); - break; - } - } - } - if (end < 1 && end > 0) - { - for (size_t i = vertices.size(); i > 0; --i) - { - if ((double)(i - 1) / vertices.size() < end) - { - vertices.erase(vertices.begin() + i, vertices.end()); - break; - } - } - } + size_t start_idx = size_t(start * vertices.size()); + size_t end_idx = size_t(end * vertices.size() + 0.5); + return std::vector(vertices.begin() + start_idx, vertices.begin() + end_idx); + } + else if (end > start) + { + size_t start_idx = size_t(end * vertices.size() + 0.5); + size_t end_idx = size_t(start * vertices.size()); + return std::vector(vertices.begin() + start_idx, vertices.begin() + end_idx); } return vertices; } diff --git a/src/modules/math/BezierCurve.h b/src/modules/math/BezierCurve.h index e35e45c08..8d01f6e3a 100644 --- a/src/modules/math/BezierCurve.h +++ b/src/modules/math/BezierCurve.h @@ -25,6 +25,8 @@ #include "common/Object.h" #include "common/Vector.h" #include +#include +#include namespace love { From 2c5f7dc896cc8acb0bbeae845e74cdf785c861e9 Mon Sep 17 00:00:00 2001 From: muddmaker Date: Mon, 22 Dec 2014 17:57:44 -0800 Subject: [PATCH 4/6] add removeControlPoint; improve exception handling --- src/modules/math/BezierCurve.cpp | 25 ++++++++++++++++++------- src/modules/math/BezierCurve.h | 8 ++++++-- src/modules/math/wrap_BezierCurve.cpp | 18 ++++++++++++++---- src/modules/math/wrap_BezierCurve.h | 1 + 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/modules/math/BezierCurve.cpp b/src/modules/math/BezierCurve.cpp index 04a23c079..06d75fef0 100644 --- a/src/modules/math/BezierCurve.cpp +++ b/src/modules/math/BezierCurve.cpp @@ -104,22 +104,22 @@ BezierCurve BezierCurve::getDerivative() const const Vector &BezierCurve::getControlPoint(int i) const { - if (i < 0) + while (i < 0) i += controlPoints.size(); - if (i < 0 || (size_t) i >= controlPoints.size()) - throw Exception("Invalid control point index"); + while ((size_t) i >= controlPoints.size()) + i -= controlPoints.size(); return controlPoints[i]; } void BezierCurve::setControlPoint(int i, const Vector &point) { - if (i < 0) + while (i < 0) i += controlPoints.size(); - if (i < 0 || (size_t) i >= controlPoints.size()) - throw Exception("Invalid control point index"); + while ((size_t) i >= controlPoints.size()) + i -= controlPoints.size(); controlPoints[i] = point; } @@ -129,12 +129,23 @@ void BezierCurve::insertControlPoint(const Vector &point, int pos) if (pos < 0) pos += controlPoints.size() + 1; - if (pos < 0 ||(size_t) pos > controlPoints.size()) + if (pos < 0 || (size_t) pos > controlPoints.size()) throw Exception("Invalid control point index"); controlPoints.insert(controlPoints.begin() + pos, point); } +void BezierCurve::removeControlPoint(int i) +{ + while (i < 0) + i += controlPoints.size(); + + while ((size_t) i >= controlPoints.size()) + i -= controlPoints.size(); + + controlPoints.erase(controlPoints.begin() + i); +} + void BezierCurve::translate(const Vector &t) { for (size_t i = 0; i < controlPoints.size(); ++i) diff --git a/src/modules/math/BezierCurve.h b/src/modules/math/BezierCurve.h index 8d01f6e3a..abb6cdc97 100644 --- a/src/modules/math/BezierCurve.h +++ b/src/modules/math/BezierCurve.h @@ -25,8 +25,6 @@ #include "common/Object.h" #include "common/Vector.h" #include -#include -#include namespace love { @@ -75,6 +73,12 @@ public: **/ void insertControlPoint(const Vector &point, int pos = -1); + /** + * Remove the i'th control point from the curve. + * @param i Control point to remove + **/ + void removeControlPoint(int i); + /** * @returns Number of control points. **/ diff --git a/src/modules/math/wrap_BezierCurve.cpp b/src/modules/math/wrap_BezierCurve.cpp index cd5b72db5..209b19497 100644 --- a/src/modules/math/wrap_BezierCurve.cpp +++ b/src/modules/math/wrap_BezierCurve.cpp @@ -54,8 +54,7 @@ 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--; + idx--; // 1-indexing luax_catchexcept(L, [&]() { Vector v = curve->getControlPoint(idx); @@ -73,8 +72,7 @@ int w_BezierCurve_setControlPoint(lua_State *L) float vx = (float) luaL_checknumber(L, 3); float vy = (float) luaL_checknumber(L, 4); - if (idx > 0) // 1-indexing - idx--; + idx--; // 1-indexing luax_catchexcept(L, [&](){ curve->setControlPoint(idx, Vector(vx,vy)); }); return 0; @@ -94,6 +92,17 @@ int w_BezierCurve_insertControlPoint(lua_State *L) return 0; } +int w_BezierCurve_removeControlPoint(lua_State *L) +{ + BezierCurve *curve = luax_checkbeziercurve(L, 1); + int idx = luaL_checkint(L, 2); + + idx--; // 1-indexing + + luax_catchexcept(L, [&](){ curve->removeControlPoint(idx); }); + return 0; +} + int w_BezierCurve_getControlPointCount(lua_State *L) { BezierCurve *curve = luax_checkbeziercurve(L, 1); @@ -194,6 +203,7 @@ static const luaL_Reg functions[] = {"getControlPoint", w_BezierCurve_getControlPoint}, {"setControlPoint", w_BezierCurve_setControlPoint}, {"insertControlPoint", w_BezierCurve_insertControlPoint}, + {"removeControlPoint", w_BezierCurve_removeControlPoint}, {"getControlPointCount", w_BezierCurve_getControlPointCount}, {"translate", w_BezierCurve_translate}, {"rotate", w_BezierCurve_rotate}, diff --git a/src/modules/math/wrap_BezierCurve.h b/src/modules/math/wrap_BezierCurve.h index 9eb6fb9bf..d36b2657d 100644 --- a/src/modules/math/wrap_BezierCurve.h +++ b/src/modules/math/wrap_BezierCurve.h @@ -36,6 +36,7 @@ int w_BezierCurve_getDerivative(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_removeControlPoint(lua_State *L); int w_BezierCurve_getControlPointCount(lua_State *L); int w_BezierCurve_translate(lua_State *L); int w_BezierCurve_rotate(lua_State *L); From 47a4cc34a518b9838d3dd908897e21ea0dd5ff92 Mon Sep 17 00:00:00 2001 From: muddmaker Date: Wed, 31 Dec 2014 23:19:07 -0800 Subject: [PATCH 5/6] universal indexing rules in BezierCurve --- changes.txt | 2 +- src/modules/math/BezierCurve.cpp | 10 +++++----- src/modules/math/wrap_BezierCurve.cpp | 9 ++++++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/changes.txt b/changes.txt index 06a651fea..5d2379490 100644 --- a/changes.txt +++ b/changes.txt @@ -23,7 +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. + * Added BezierCurve:renderSegment and BexierCurve:removePoint. * Deprecated SpriteBatch:bind and SpriteBatch:unbind. * Deprecated all uses of the name 'FSAA' in favor of 'MSAA'. diff --git a/src/modules/math/BezierCurve.cpp b/src/modules/math/BezierCurve.cpp index 06d75fef0..59d5f1486 100644 --- a/src/modules/math/BezierCurve.cpp +++ b/src/modules/math/BezierCurve.cpp @@ -124,15 +124,15 @@ void BezierCurve::setControlPoint(int i, const Vector &point) controlPoints[i] = point; } -void BezierCurve::insertControlPoint(const Vector &point, int pos) +void BezierCurve::insertControlPoint(const Vector &point, int i) { - if (pos < 0) - pos += controlPoints.size() + 1; + while (i < 0) + i += controlPoints.size() + 1; - if (pos < 0 || (size_t) pos > controlPoints.size()) + while ((size_t) i > controlPoints.size()) throw Exception("Invalid control point index"); - controlPoints.insert(controlPoints.begin() + pos, point); + controlPoints.insert(controlPoints.begin() + i, point); } void BezierCurve::removeControlPoint(int i) diff --git a/src/modules/math/wrap_BezierCurve.cpp b/src/modules/math/wrap_BezierCurve.cpp index 209b19497..e0ef5bf5c 100644 --- a/src/modules/math/wrap_BezierCurve.cpp +++ b/src/modules/math/wrap_BezierCurve.cpp @@ -54,7 +54,8 @@ int w_BezierCurve_getControlPoint(lua_State *L) BezierCurve *curve = luax_checkbeziercurve(L, 1); int idx = luaL_checkinteger(L, 2); - idx--; // 1-indexing + if (idx > 0) // 1-indexing + idx--; luax_catchexcept(L, [&]() { Vector v = curve->getControlPoint(idx); @@ -72,7 +73,8 @@ int w_BezierCurve_setControlPoint(lua_State *L) float vx = (float) luaL_checknumber(L, 3); float vy = (float) luaL_checknumber(L, 4); - idx--; // 1-indexing + if (idx > 0) // 1-indexing + idx--; luax_catchexcept(L, [&](){ curve->setControlPoint(idx, Vector(vx,vy)); }); return 0; @@ -97,7 +99,8 @@ int w_BezierCurve_removeControlPoint(lua_State *L) BezierCurve *curve = luax_checkbeziercurve(L, 1); int idx = luaL_checkint(L, 2); - idx--; // 1-indexing + if (idx > 0) // 1-indexing + idx--; luax_catchexcept(L, [&](){ curve->removeControlPoint(idx); }); return 0; From 8ee2db342018930a26dce2c92b4a76e327ec000d Mon Sep 17 00:00:00 2001 From: muddmaker Date: Sun, 22 Mar 2015 10:16:12 -0700 Subject: [PATCH 6/6] Fix typos --- src/modules/math/BezierCurve.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules/math/BezierCurve.cpp b/src/modules/math/BezierCurve.cpp index 134babd56..4cbe984dd 100644 --- a/src/modules/math/BezierCurve.cpp +++ b/src/modules/math/BezierCurve.cpp @@ -127,10 +127,10 @@ void BezierCurve::setControlPoint(int i, const Vector &point) void BezierCurve::insertControlPoint(const Vector &point, int i) { while (i < 0) - i += controlPoints.size() + 1; + i += controlPoints.size(); while ((size_t) i > controlPoints.size()) - throw Exception("Invalid control point index"); + i -= controlPoints.size(); controlPoints.insert(controlPoints.begin() + i, point); } @@ -139,13 +139,13 @@ void BezierCurve::removeControlPoint(int i) { while (i < 0) i += controlPoints.size(); - + while ((size_t) i >= controlPoints.size()) i -= controlPoints.size(); - + controlPoints.erase(controlPoints.begin() + i); } - + void BezierCurve::translate(const Vector &t) { for (size_t i = 0; i < controlPoints.size(); ++i) @@ -181,7 +181,7 @@ Vector BezierCurve::evaluate(double t) const 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]; }