mirror of
https://github.com/love2d/love.git
synced 2026-08-20 04:30:09 +02:00
[BezierCurve] Add getDerivative(), move(), rotate() and scale().
This commit is contained in:
@@ -22,7 +22,7 @@
|
|||||||
#include "BezierCurve.h"
|
#include "BezierCurve.h"
|
||||||
#include "common/Exception.h"
|
#include "common/Exception.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <cmath>
|
||||||
|
|
||||||
using namespace std;
|
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
|
const Vector &BezierCurve::getControlPoint(int i) const
|
||||||
{
|
{
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
@@ -120,6 +135,29 @@ void BezierCurve::insertControlPoint(const Vector &point, int pos)
|
|||||||
controlPoints.insert(controlPoints.begin() + pos, point);
|
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
|
Vector BezierCurve::eval(double t) const
|
||||||
{
|
{
|
||||||
if (t < 0 || t > 1)
|
if (t < 0 || t > 1)
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ public:
|
|||||||
return controlPoints.size() - 1;
|
return controlPoints.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns First derivative of the curve.
|
||||||
|
*/
|
||||||
|
BezierCurve getDerivative() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns i'th control point.
|
* @returns i'th control point.
|
||||||
**/
|
**/
|
||||||
@@ -68,6 +73,26 @@ public:
|
|||||||
**/
|
**/
|
||||||
void insertControlPoint(const Vector &point, int pos = -1);
|
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.
|
* Evaluates the curve at time t.
|
||||||
* @param t Curve parameter, must satisfy 0 <= t <= 1.
|
* @param t Curve parameter, must satisfy 0 <= t <= 1.
|
||||||
|
|||||||
@@ -40,6 +40,14 @@ int w_BezierCurve_getDegree(lua_State *L)
|
|||||||
return 1;
|
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)
|
int w_BezierCurve_getControlPoint(lua_State *L)
|
||||||
{
|
{
|
||||||
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
||||||
@@ -106,6 +114,35 @@ int w_BezierCurve_insertControlPoint(lua_State *L)
|
|||||||
return 0;
|
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)
|
int w_BezierCurve_eval(lua_State *L)
|
||||||
{
|
{
|
||||||
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
||||||
@@ -148,9 +185,13 @@ int w_BezierCurve_render(lua_State *L)
|
|||||||
static const luaL_Reg functions[] =
|
static const luaL_Reg functions[] =
|
||||||
{
|
{
|
||||||
{"getDegree", w_BezierCurve_getDegree},
|
{"getDegree", w_BezierCurve_getDegree},
|
||||||
|
{"getDerivative", w_BezierCurve_getDerivative},
|
||||||
{"getControlPoint", w_BezierCurve_getControlPoint},
|
{"getControlPoint", w_BezierCurve_getControlPoint},
|
||||||
{"setControlPoint", w_BezierCurve_setControlPoint},
|
{"setControlPoint", w_BezierCurve_setControlPoint},
|
||||||
{"insertControlPoint", w_BezierCurve_insertControlPoint},
|
{"insertControlPoint", w_BezierCurve_insertControlPoint},
|
||||||
|
{"move", w_BezierCurve_move},
|
||||||
|
{"rotate", w_BezierCurve_rotate},
|
||||||
|
{"scale", w_BezierCurve_scale},
|
||||||
{"eval", w_BezierCurve_eval},
|
{"eval", w_BezierCurve_eval},
|
||||||
{"render", w_BezierCurve_render},
|
{"render", w_BezierCurve_render},
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
|
|||||||
@@ -32,9 +32,13 @@ namespace math
|
|||||||
|
|
||||||
BezierCurve *luax_checkbeziercurve(lua_State *L, int idx);
|
BezierCurve *luax_checkbeziercurve(lua_State *L, int idx);
|
||||||
int w_BezierCurve_getDegree(lua_State *L);
|
int w_BezierCurve_getDegree(lua_State *L);
|
||||||
|
int w_BezierCurve_getDerivative(lua_State *L);
|
||||||
int w_BezierCurve_getControlPoint(lua_State *L);
|
int w_BezierCurve_getControlPoint(lua_State *L);
|
||||||
int w_BezierCurve_setControlPoint(lua_State *L);
|
int w_BezierCurve_setControlPoint(lua_State *L);
|
||||||
int w_BezierCurve_insertControlPoint(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_eval(lua_State *L);
|
||||||
int w_BezierCurve_render(lua_State *L);
|
int w_BezierCurve_render(lua_State *L);
|
||||||
extern "C" int luaopen_beziercurve(lua_State *L);
|
extern "C" int luaopen_beziercurve(lua_State *L);
|
||||||
|
|||||||
Reference in New Issue
Block a user