소스 검색

[BezierCurve] Add getDerivative(), move(), rotate() and scale().

vrld 12 년 전
부모
커밋
983496238f
4개의 변경된 파일109개의 추가작업 그리고 1개의 파일을 삭제
  1. 39 1
      src/modules/math/BezierCurve.cpp
  2. 25 0
      src/modules/math/BezierCurve.h
  3. 41 0
      src/modules/math/wrap_BezierCurve.cpp
  4. 4 0
      src/modules/math/wrap_BezierCurve.h

+ 39 - 1
src/modules/math/BezierCurve.cpp

@@ -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 &center)
+{
+	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 &center)
+{
+	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)

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

@@ -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 &center);
+
+	/**
+	 * Scale the curve.
+	 * @param s Scale factor.
+	 * @param center Scale center.
+	 */
+	void scale(double phi, const Vector &center);
+
 	/**
 	 * Evaluates the curve at time t.
 	 * @param t Curve parameter, must satisfy 0 <= t <= 1.

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

@@ -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 }

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

@@ -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);