mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-11 21:27:01 -04:00
ce906e83f8
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1178 0fc631ac-6414-0410-93d0-97cfa31319b6
127 lines
5.9 KiB
C++
127 lines
5.9 KiB
C++
//+----------------------------------------------------------------------------+
|
|
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
|
//| Copyright: (C) 2001 - 2008 Twan van Laarhoven and "coppro" |
|
|
//| License: GNU General Public License 2 or later (see file COPYING) |
|
|
//+----------------------------------------------------------------------------+
|
|
|
|
#ifndef HEADER_GFX_BEZIER
|
|
#define HEADER_GFX_BEZIER
|
|
|
|
/** @file gfx/bezier.hpp
|
|
*
|
|
* Bezier curve and line related functions
|
|
*/
|
|
|
|
// ----------------------------------------------------------------------------- : Includes
|
|
|
|
#include <util/prec.hpp>
|
|
#include <util/vector2d.hpp>
|
|
#include <data/symbol.hpp>
|
|
|
|
class Rotation;
|
|
|
|
// ----------------------------------------------------------------------------- : Evaluation
|
|
|
|
/// A bezier curve for evaluation
|
|
class BezierCurve {
|
|
public:
|
|
/// coefficients of the equation (x,y) = at^3 + bt^2 + ct + d
|
|
Vector2D a, b, c, d;
|
|
|
|
/// Construct a bezier curve evaluator given the 4 handles
|
|
BezierCurve(const Vector2D& p0, const Vector2D& p1, const Vector2D& p2, const Vector2D& p3);
|
|
|
|
/// Construct a bezier curve evaluator given two ControlPoints at the ends
|
|
BezierCurve(const ControlPoint& p0, const ControlPoint& p3);
|
|
|
|
/// Return the point on this curve at time t in [0...1)
|
|
inline Vector2D pointAt(double t) const {
|
|
return d + (c + (b + a * t) * t) * t;
|
|
}
|
|
|
|
/// Return the tangent on this curve at time t in [0...1)
|
|
inline Vector2D tangentAt(double t) const {
|
|
return c + ((b * 2) + (a * 3) * t) * t;
|
|
}
|
|
};
|
|
|
|
/// Subdivide a curve from a to b, store the result in a control point
|
|
/** Also modifies the handles of the points to accomodate the inserted point
|
|
* Direct version, using input curve a1,a2,a3,a4 and output curves a1,b2,b3,b4 and c1,c2,c3,a4
|
|
*/
|
|
void deCasteljau(Vector2D a1, Vector2D a2, Vector2D a3, Vector2D a4,
|
|
Vector2D& b2, Vector2D& b3, Vector2D& b4c1,
|
|
Vector2D& c2, Vector2D& c3, double t);
|
|
|
|
/// Subdivide a curve from a to b at time t
|
|
/** Stores the point at time t in mid, updates the handles of a and b!
|
|
*/
|
|
void deCasteljau(ControlPoint& a, ControlPoint& b, double t, ControlPoint& mid);
|
|
|
|
/// Subdivide a curve from a to b, store the result in a control point
|
|
/** Also modifies the handles of the points to accomodate the inserted point!
|
|
*/
|
|
void deCasteljau(const Vector2D& a1, Vector2D& a21, Vector2D& a34, const Vector2D& a4, double t, ControlPoint& out);
|
|
|
|
// ----------------------------------------------------------------------------- : Drawing
|
|
|
|
/// Devide a segment into a number of straight lines for display purposes
|
|
/** Adds the resulting corner points of those lines to out, the last point is not added.
|
|
* All points are converted to display coordinates by multiplying with m and adding origin
|
|
*/
|
|
void segment_subdivide(const ControlPoint& p0, const ControlPoint& p1, const Vector2D& origin, const Matrix2D& m, vector<wxPoint>& out);
|
|
|
|
// ----------------------------------------------------------------------------- : Bounds
|
|
|
|
/// Find a bounding box that fits a segment (either a line or a bezier curve) between p1 and p2.
|
|
/** stores the results in min and max.
|
|
* min is only changed if the minimum is smaller then the current value in min,
|
|
* max only if the maximum is larger.
|
|
*/
|
|
Bounds segment_bounds(const Vector2D& origin, const Matrix2D& m, const ControlPoint& p1, const ControlPoint& p2);
|
|
|
|
/// Find a bounding box that fits a curve between p1 and p2, stores the results in min and max.
|
|
/** min is only changed if the minimum is smaller then the current value in min,
|
|
* max only if the maximum is larger
|
|
*/
|
|
Bounds bezier_bounds(const Vector2D& origin, const Matrix2D& m, const ControlPoint& p1, const ControlPoint& p2);
|
|
|
|
/// Find a bounding box that fits around p1 and p2, stores the result in min and max
|
|
/** min is only changed if the minimum is smaller then the current value in min,
|
|
* max only if the maximum is larger
|
|
*/
|
|
Bounds line_bounds(const Vector2D& origin, const Matrix2D& m, const Vector2D& p1, const Vector2D& p2);
|
|
|
|
// ----------------------------------------------------------------------------- : Point tests
|
|
|
|
/// Is a point inside the given shape?
|
|
bool point_in_shape(const Vector2D& p, const SymbolShape& part);
|
|
|
|
// ----------------------------------------------------------------------------- : Finding points
|
|
|
|
/// Finds the position of p0 on the line between p1 and p2, returns true if the point is on (or near) the line
|
|
/// the line between p1 and p2 can also be a bezier curve
|
|
/** Returns the time on the segment in tOut, and the point on the segment in pOut
|
|
*/
|
|
bool pos_on_segment(const Vector2D& pos, double range, const ControlPoint& p1, const ControlPoint& p2, Vector2D& pOut, double& tOut);
|
|
|
|
/// Finds the position of p0 on the line between p1 and p2, returns true if the point is on (or near)
|
|
/// the bezier curve between p1 and p2
|
|
bool pos_on_bezier (const Vector2D& pos, double range, const ControlPoint& p1, const ControlPoint& p2, Vector2D& pOut, double& tOut);
|
|
|
|
/// Finds the position of p0 on the line p1-p2, returns true if the point is withing range of the line
|
|
/// if that is the case then (x,y) = p1 + (p2-p1) * out
|
|
bool pos_on_line (const Vector2D& pos, double range, const Vector2D& p1, const Vector2D& p2, Vector2D& pOut, double& tOut);
|
|
|
|
// ----------------------------------------------------------------------------- : Intersection
|
|
|
|
/// Counts the number of intersections between the ray/halfline from (-inf, pos.y) to pos
|
|
/// and the bezier curve between p1 and p2.
|
|
UInt intersect_bezier_ray(const ControlPoint& p1, const ControlPoint& p2, const Vector2D& pos);
|
|
|
|
// Does the line between p1 and p2 intersect the ray (half line) from (-inf, pos.y) to pos?
|
|
bool intersect_line_ray(const Vector2D& p1, const Vector2D& p2, const Vector2D& pos);
|
|
|
|
// ----------------------------------------------------------------------------- : EOF
|
|
#endif
|