Implemented finding of nearest point to spline classes.

Originally committed to SVN as r1389.
This commit is contained in:
Rodrigo Braz Monteiro 2007-07-07 08:53:11 +00:00
parent ee832d642d
commit 14ade371f3
7 changed files with 137 additions and 32 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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