mirror of
https://github.com/love2d/love.git
synced 2026-08-16 08:11:02 +02:00
[BezierCurve] Add getDerivative(), move(), rotate() and scale().
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
#include "BezierCurve.h"
|
||||
#include "common/Exception.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -87,6 +87,21 @@ BezierCurve::BezierCurve(const vector<Vector> &pts)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BezierCurve BezierCurve::getDerivative() const
|
||||
{
|
||||
if (getDegree() < 1)
|
||||
throw Exception("Cannot derive a curve of degree < 1.");
|
||||
// actually we can, it just doesn't make any sense.
|
||||
|
||||
vector<Vector> forward_differences(controlPoints.size()-1);
|
||||
float degree = float(getDegree());
|
||||
for (size_t i = 0; i < forward_differences.size(); ++i)
|
||||
forward_differences[i] = (controlPoints[i+1] - controlPoints[i]) * degree;
|
||||
|
||||
return BezierCurve(forward_differences);
|
||||
}
|
||||
|
||||
const Vector &BezierCurve::getControlPoint(int i) const
|
||||
{
|
||||
if (i < 0)
|
||||
@@ -120,6 +135,29 @@ void BezierCurve::insertControlPoint(const Vector &point, int pos)
|
||||
controlPoints.insert(controlPoints.begin() + pos, point);
|
||||
}
|
||||
|
||||
void BezierCurve::translate(const Vector &t)
|
||||
{
|
||||
for (size_t i = 0; i < controlPoints.size(); ++i)
|
||||
controlPoints[i] += t;
|
||||
}
|
||||
|
||||
void BezierCurve::rotate(double phi, const Vector ¢er)
|
||||
{
|
||||
float c = cos(phi), s = sin(phi);
|
||||
for (size_t i = 0; i < controlPoints.size(); ++i)
|
||||
{
|
||||
Vector v = controlPoints[i] - center;
|
||||
controlPoints[i].x = c * v.x - s * v.y + center.x;
|
||||
controlPoints[i].y = s * v.x + c * v.y + center.y;
|
||||
}
|
||||
}
|
||||
|
||||
void BezierCurve::scale(double s, const Vector ¢er)
|
||||
{
|
||||
for (size_t i = 0; i < controlPoints.size(); ++i)
|
||||
controlPoints[i] = (controlPoints[i] - center) * s + center;
|
||||
}
|
||||
|
||||
Vector BezierCurve::eval(double t) const
|
||||
{
|
||||
if (t < 0 || t > 1)
|
||||
|
||||
@@ -48,6 +48,11 @@ public:
|
||||
return controlPoints.size() - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns First derivative of the curve.
|
||||
*/
|
||||
BezierCurve getDerivative() const;
|
||||
|
||||
/**
|
||||
* @returns i'th control point.
|
||||
**/
|
||||
@@ -68,6 +73,26 @@ public:
|
||||
**/
|
||||
void insertControlPoint(const Vector &point, int pos = -1);
|
||||
|
||||
/**
|
||||
* Move the curve.
|
||||
* @param t Translation vector.
|
||||
*/
|
||||
void translate(const Vector &t);
|
||||
|
||||
/**
|
||||
* Rotate the curve.
|
||||
* @param phi Rotation angle (radians).
|
||||
* @param center Rotation center.
|
||||
*/
|
||||
void rotate(double phi, const Vector ¢er);
|
||||
|
||||
/**
|
||||
* Scale the curve.
|
||||
* @param s Scale factor.
|
||||
* @param center Scale center.
|
||||
*/
|
||||
void scale(double phi, const Vector ¢er);
|
||||
|
||||
/**
|
||||
* Evaluates the curve at time t.
|
||||
* @param t Curve parameter, must satisfy 0 <= t <= 1.
|
||||
|
||||
@@ -40,6 +40,14 @@ int w_BezierCurve_getDegree(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_BezierCurve_getDerivative(lua_State *L)
|
||||
{
|
||||
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
||||
BezierCurve *deriv = new BezierCurve(curve->getDerivative());
|
||||
luax_newtype(L, "BezierCurve", MATH_BEZIER_CURVE_T, (void *)deriv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_BezierCurve_getControlPoint(lua_State *L)
|
||||
{
|
||||
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
||||
@@ -106,6 +114,35 @@ int w_BezierCurve_insertControlPoint(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_BezierCurve_move(lua_State *L)
|
||||
{
|
||||
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
||||
double dx = luaL_checknumber(L, 2);
|
||||
double dy = luaL_checknumber(L, 3);
|
||||
curve->translate(Vector(dx,dy));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_BezierCurve_rotate(lua_State *L)
|
||||
{
|
||||
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
||||
double phi = luaL_checknumber(L, 2);
|
||||
double ox = luaL_optnumber(L, 3, 0);
|
||||
double oy = luaL_optnumber(L, 4, 0);
|
||||
curve->rotate(phi, Vector(ox,oy));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_BezierCurve_scale(lua_State *L)
|
||||
{
|
||||
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
||||
double s = luaL_checknumber(L, 2);
|
||||
double ox = luaL_optnumber(L, 3, 0);
|
||||
double oy = luaL_optnumber(L, 4, 0);
|
||||
curve->scale(s, Vector(ox,oy));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_BezierCurve_eval(lua_State *L)
|
||||
{
|
||||
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
||||
@@ -148,9 +185,13 @@ int w_BezierCurve_render(lua_State *L)
|
||||
static const luaL_Reg functions[] =
|
||||
{
|
||||
{"getDegree", w_BezierCurve_getDegree},
|
||||
{"getDerivative", w_BezierCurve_getDerivative},
|
||||
{"getControlPoint", w_BezierCurve_getControlPoint},
|
||||
{"setControlPoint", w_BezierCurve_setControlPoint},
|
||||
{"insertControlPoint", w_BezierCurve_insertControlPoint},
|
||||
{"move", w_BezierCurve_move},
|
||||
{"rotate", w_BezierCurve_rotate},
|
||||
{"scale", w_BezierCurve_scale},
|
||||
{"eval", w_BezierCurve_eval},
|
||||
{"render", w_BezierCurve_render},
|
||||
{ 0, 0 }
|
||||
|
||||
@@ -32,9 +32,13 @@ namespace math
|
||||
|
||||
BezierCurve *luax_checkbeziercurve(lua_State *L, int idx);
|
||||
int w_BezierCurve_getDegree(lua_State *L);
|
||||
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_move(lua_State *L);
|
||||
int w_BezierCurve_rotate(lua_State *L);
|
||||
int w_BezierCurve_scale(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);
|
||||
|
||||
Reference in New Issue
Block a user