mirror of https://github.com/odrling/Aegisub
Implemented finding of nearest point to spline classes.
Originally committed to SVN as r1389.
This commit is contained in:
parent
ee832d642d
commit
14ade371f3
|
@ -261,18 +261,10 @@ void Spline::GetPointList(std::vector<Vector2D> &points) {
|
||||||
// Generate points for each curve
|
// Generate points for each curve
|
||||||
for (std::list<SplineCurve>::iterator cur = curves.begin();cur!=curves.end();cur++) {
|
for (std::list<SplineCurve>::iterator cur = curves.begin();cur!=curves.end();cur++) {
|
||||||
// First point
|
// First point
|
||||||
if (isFirst) {
|
if (isFirst) points.push_back(cur->p1);
|
||||||
pt.x = cur->p1.x;
|
|
||||||
pt.y = cur->p1.y;
|
|
||||||
points.push_back(pt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line
|
// Line
|
||||||
if (cur->type == CURVE_LINE) {
|
if (cur->type == CURVE_LINE) points.push_back(cur->p2);
|
||||||
pt.x = cur->p2.x;
|
|
||||||
pt.y = cur->p2.y;
|
|
||||||
points.push_back(pt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bicubic
|
// Bicubic
|
||||||
else if (cur->type == CURVE_BICUBIC) {
|
else if (cur->type == CURVE_BICUBIC) {
|
||||||
|
@ -290,11 +282,7 @@ void Spline::GetPointList(std::vector<Vector2D> &points) {
|
||||||
for (int i=0;i<steps;i++) {
|
for (int i=0;i<steps;i++) {
|
||||||
// Get t and t-1 (u)
|
// Get t and t-1 (u)
|
||||||
float t = float(i)/float(steps);
|
float t = float(i)/float(steps);
|
||||||
float u = 1.0f-t;
|
points.push_back(cur->GetPoint(t));
|
||||||
|
|
||||||
// Calculate the point and insert it
|
|
||||||
pt = p1*u*u*u + 3*p2*t*u*u + 3*p3*t*t*u + p4*t*t*t;
|
|
||||||
points.push_back(pt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,16 +296,47 @@ void Spline::GetPointList(std::vector<Vector2D> &points) {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
// t value and curve of the point closest to reference
|
// t value and curve of the point closest to reference
|
||||||
void GetClosestParametricPoint(Vector2D reference,int &curve,float &t) {
|
void Spline::GetClosestParametricPoint(Vector2D reference,int &curve,float &t,Vector2D &pt) {
|
||||||
// TODO
|
// Has at least one curve?
|
||||||
|
curve = 0;
|
||||||
|
t = 0.0f;
|
||||||
|
if (curves.size() == 0) return;
|
||||||
|
|
||||||
|
// Close the shape
|
||||||
|
SplineCurve pad;
|
||||||
|
pad.p1 = curves.back().GetEndPoint();
|
||||||
|
pad.p2 = curves.front().p1;
|
||||||
|
pad.type = CURVE_LINE;
|
||||||
|
curves.push_back(pad);
|
||||||
|
|
||||||
|
// Prepare
|
||||||
|
float closest = 8000000.0f;
|
||||||
|
int i = 0;
|
||||||
|
for (std::list<SplineCurve>::iterator cur = curves.begin();cur!=curves.end();cur++,i++) {
|
||||||
|
float param = cur->GetClosestParam(reference);
|
||||||
|
Vector2D p1 = cur->GetPoint(param);
|
||||||
|
float dist = (p1-reference).Len();
|
||||||
|
if (dist < closest) {
|
||||||
|
closest = dist;
|
||||||
|
t = param;
|
||||||
|
curve = i;
|
||||||
|
pt = p1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove closing and return
|
||||||
|
curves.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
// Point closest to reference
|
// Point closest to reference
|
||||||
Vector2D Spline::GetClosestPoint(Vector2D reference) {
|
Vector2D Spline::GetClosestPoint(Vector2D reference) {
|
||||||
// TODO
|
int curve;
|
||||||
return Vector2D(-1,-1);
|
float t;
|
||||||
|
Vector2D point;
|
||||||
|
GetClosestParametricPoint(reference,curve,t,point);
|
||||||
|
return point;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ public:
|
||||||
|
|
||||||
void GetPointList(std::vector<Vector2D> &points);
|
void GetPointList(std::vector<Vector2D> &points);
|
||||||
|
|
||||||
void GetClosestParametricPoint(Vector2D reference,int &curve,float &t);
|
void GetClosestParametricPoint(Vector2D reference,int &curve,float &t,Vector2D &point);
|
||||||
Vector2D GetClosestPoint(Vector2D reference);
|
Vector2D GetClosestPoint(Vector2D reference);
|
||||||
Vector2D GetClosestControlPoint(Vector2D reference);
|
Vector2D GetClosestControlPoint(Vector2D reference);
|
||||||
};
|
};
|
||||||
|
|
|
@ -120,12 +120,33 @@ void SplineCurve::Smooth(Vector2D P0,Vector2D P3,float smooth) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// Get a point
|
||||||
|
Vector2D SplineCurve::GetPoint(float t) const {
|
||||||
|
// Point
|
||||||
|
if (type == CURVE_POINT) return p1;
|
||||||
|
|
||||||
|
// Line
|
||||||
|
else if (type == CURVE_LINE) {
|
||||||
|
return p1*(1.0f-t) + p2*t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bicubic
|
||||||
|
else if (type == CURVE_BICUBIC) {
|
||||||
|
float u = 1.0f-t;
|
||||||
|
return p1*u*u*u + 3*p2*t*u*u + 3*p3*t*t*u + p4*t*t*t;
|
||||||
|
}
|
||||||
|
|
||||||
|
else return Vector2D(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// Get start/end point
|
// Get start/end point
|
||||||
Vector2D SplineCurve::GetStartPoint() {
|
Vector2D SplineCurve::GetStartPoint() const {
|
||||||
return p1;
|
return p1;
|
||||||
}
|
}
|
||||||
Vector2D SplineCurve::GetEndPoint() {
|
Vector2D SplineCurve::GetEndPoint() const {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CURVE_POINT: return p1;
|
case CURVE_POINT: return p1;
|
||||||
case CURVE_LINE: return p2;
|
case CURVE_LINE: return p2;
|
||||||
|
@ -133,3 +154,48 @@ Vector2D SplineCurve::GetEndPoint() {
|
||||||
default: return p1;
|
default: return p1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////
|
||||||
|
// Get point closest to reference
|
||||||
|
Vector2D SplineCurve::GetClosestPoint(Vector2D ref) const {
|
||||||
|
return GetPoint(GetClosestParam(ref));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////
|
||||||
|
// Get value of parameter closest to point
|
||||||
|
float SplineCurve::GetClosestParam(Vector2D ref) const {
|
||||||
|
// Line
|
||||||
|
if (type == CURVE_LINE) {
|
||||||
|
//return MID(0.0f,((ref.x-p1.x)*(p2.x-p1.x) + (ref.y-p1.y)*(p2.y-p1.y))/(p2-p1).SquareLen(),1.0f);
|
||||||
|
return MID(0.0f,(ref-p1).Dot(p2-p1)/(p2-p1).SquareLen(),1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bicubic
|
||||||
|
if (type == CURVE_BICUBIC) {
|
||||||
|
int steps = 100;
|
||||||
|
float bestDist = 80000000.0f;
|
||||||
|
float bestT = 0.0f;
|
||||||
|
for (int i=0;i<=steps;i++) {
|
||||||
|
float t = float(i)/float(steps);
|
||||||
|
float dist = (GetPoint(t)-ref).Len();
|
||||||
|
if (dist < bestDist) {
|
||||||
|
bestDist = dist;
|
||||||
|
bestT = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bestT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Something else
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// Quick distance
|
||||||
|
float SplineCurve::GetQuickDistance(Vector2D ref) const {
|
||||||
|
if (type == CURVE_BICUBIC) return MIN(MIN((ref-p1).Len(),(ref-p2).Len()),MIN((ref-p3).Len(),(ref-p4).Len()));
|
||||||
|
else return (GetClosestPoint(ref)-ref).Len();
|
||||||
|
}
|
||||||
|
|
|
@ -62,6 +62,11 @@ public:
|
||||||
SplineCurve();
|
SplineCurve();
|
||||||
void Split(SplineCurve &c1,SplineCurve &c2,float t=0.5);
|
void Split(SplineCurve &c1,SplineCurve &c2,float t=0.5);
|
||||||
void Smooth(Vector2D prev,Vector2D next,float smooth=1.0f);
|
void Smooth(Vector2D prev,Vector2D next,float smooth=1.0f);
|
||||||
Vector2D GetStartPoint();
|
|
||||||
Vector2D GetEndPoint();
|
Vector2D GetPoint(float t) const;
|
||||||
|
Vector2D GetStartPoint() const;
|
||||||
|
Vector2D GetEndPoint() const;
|
||||||
|
Vector2D GetClosestPoint(Vector2D ref) const;
|
||||||
|
float GetClosestParam(Vector2D ref) const;
|
||||||
|
float GetQuickDistance(Vector2D ref) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -109,14 +109,14 @@ Vector2D Vector2D::operator -= (const Vector2D param) {
|
||||||
|
|
||||||
//////////
|
//////////
|
||||||
// Negate
|
// Negate
|
||||||
Vector2D Vector2D::operator - () {
|
Vector2D Vector2D::operator - () const {
|
||||||
return Vector2D(-x,-y);
|
return Vector2D(-x,-y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
// Multiplication by scalar
|
// Multiplication by scalar
|
||||||
Vector2D Vector2D::operator * (float param) {
|
Vector2D Vector2D::operator * (float param) const {
|
||||||
return Vector2D(x * param,y * param);
|
return Vector2D(x * param,y * param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ Vector2D operator * (float f,const Vector2D &v) {
|
||||||
|
|
||||||
//////////////////////
|
//////////////////////
|
||||||
// Division by scalar
|
// Division by scalar
|
||||||
Vector2D Vector2D::operator / (float param) {
|
Vector2D Vector2D::operator / (float param) const {
|
||||||
return Vector2D(x / param,y / param);
|
return Vector2D(x / param,y / param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,9 +169,16 @@ float Vector2D::Len () const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// Squared Length
|
||||||
|
float Vector2D::SquareLen () const {
|
||||||
|
return x*x + y*y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
// Unitary
|
// Unitary
|
||||||
Vector2D Vector2D::Unit () {
|
Vector2D Vector2D::Unit () const {
|
||||||
float l = Len();
|
float l = Len();
|
||||||
if (l != 0) {
|
if (l != 0) {
|
||||||
Vector2D temp;
|
Vector2D temp;
|
||||||
|
|
|
@ -51,23 +51,25 @@ public:
|
||||||
bool operator == (const Vector2D param) const;
|
bool operator == (const Vector2D param) const;
|
||||||
bool operator != (const Vector2D param) const;
|
bool operator != (const Vector2D param) const;
|
||||||
|
|
||||||
Vector2D operator - ();
|
Vector2D operator - () const;
|
||||||
Vector2D operator + (const Vector2D param) const;
|
Vector2D operator + (const Vector2D param) const;
|
||||||
Vector2D operator - (const Vector2D param) const;
|
Vector2D operator - (const Vector2D param) const;
|
||||||
Vector2D operator * (float param);
|
Vector2D operator * (float param) const;
|
||||||
Vector2D operator / (float param);
|
Vector2D operator / (float param) const;
|
||||||
|
|
||||||
Vector2D operator += (const Vector2D param);
|
Vector2D operator += (const Vector2D param);
|
||||||
Vector2D operator -= (const Vector2D param);
|
Vector2D operator -= (const Vector2D param);
|
||||||
Vector2D operator *= (float param);
|
Vector2D operator *= (float param);
|
||||||
Vector2D operator /= (float param);
|
Vector2D operator /= (float param);
|
||||||
|
|
||||||
Vector2D Unit ();
|
Vector2D Unit () const;
|
||||||
float Cross (const Vector2D param) const;
|
float Cross (const Vector2D param) const;
|
||||||
float Dot (const Vector2D param) const;
|
float Dot (const Vector2D param) const;
|
||||||
|
|
||||||
float Len () const;
|
float Len () const;
|
||||||
float Length () const { return Len(); }
|
float Length () const { return Len(); }
|
||||||
|
float SquareLen () const;
|
||||||
|
float SquareLength () const { return SquareLen(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,12 @@ void VisualToolVectorClip::Draw() {
|
||||||
DrawDashedLine(mx,my,c1->GetEndPoint().x,c1->GetEndPoint().y,6);
|
DrawDashedLine(mx,my,c1->GetEndPoint().x,c1->GetEndPoint().y,6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw preview of insert point
|
||||||
|
if (mode == 4) {
|
||||||
|
Vector2D p1 = spline.GetClosestPoint(Vector2D(mx,my));
|
||||||
|
DrawCircle(p1.x,p1.y,4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue