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
for (std::list<SplineCurve>::iterator cur = curves.begin();cur!=curves.end();cur++) {
// First point
if (isFirst) {
pt.x = cur->p1.x;
pt.y = cur->p1.y;
points.push_back(pt);
}
if (isFirst) points.push_back(cur->p1);
// Line
if (cur->type == CURVE_LINE) {
pt.x = cur->p2.x;
pt.y = cur->p2.y;
points.push_back(pt);
}
if (cur->type == CURVE_LINE) points.push_back(cur->p2);
// 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++) {
// Get t and t-1 (u)
float t = float(i)/float(steps);
float u = 1.0f-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);
points.push_back(cur->GetPoint(t));
}
}
}
@ -308,16 +296,47 @@ void Spline::GetPointList(std::vector<Vector2D> &points) {
///////////////////////////////////////////////////////
// t value and curve of the point closest to reference
void GetClosestParametricPoint(Vector2D reference,int &curve,float &t) {
// TODO
void Spline::GetClosestParametricPoint(Vector2D reference,int &curve,float &t,Vector2D &pt) {
// 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
Vector2D Spline::GetClosestPoint(Vector2D reference) {
// TODO
return Vector2D(-1,-1);
int curve;
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 GetClosestParametricPoint(Vector2D reference,int &curve,float &t);
void GetClosestParametricPoint(Vector2D reference,int &curve,float &t,Vector2D &point);
Vector2D GetClosestPoint(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
Vector2D SplineCurve::GetStartPoint() {
Vector2D SplineCurve::GetStartPoint() const {
return p1;
}
Vector2D SplineCurve::GetEndPoint() {
Vector2D SplineCurve::GetEndPoint() const {
switch (type) {
case CURVE_POINT: return p1;
case CURVE_LINE: return p2;
@ -133,3 +154,48 @@ Vector2D SplineCurve::GetEndPoint() {
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();
void Split(SplineCurve &c1,SplineCurve &c2,float t=0.5);
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
Vector2D Vector2D::operator - () {
Vector2D Vector2D::operator - () const {
return Vector2D(-x,-y);
}
////////////////////////////
// Multiplication by scalar
Vector2D Vector2D::operator * (float param) {
Vector2D Vector2D::operator * (float param) const {
return Vector2D(x * param,y * param);
}
@ -133,7 +133,7 @@ Vector2D operator * (float f,const Vector2D &v) {
//////////////////////
// Division by scalar
Vector2D Vector2D::operator / (float param) {
Vector2D Vector2D::operator / (float param) const {
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
Vector2D Vector2D::Unit () {
Vector2D Vector2D::Unit () const {
float l = Len();
if (l != 0) {
Vector2D temp;

View file

@ -51,23 +51,25 @@ public:
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 * (float param);
Vector2D operator / (float param);
Vector2D operator * (float param) const;
Vector2D operator / (float param) const;
Vector2D operator += (const Vector2D param);
Vector2D operator -= (const Vector2D param);
Vector2D operator *= (float param);
Vector2D operator /= (float param);
Vector2D Unit ();
Vector2D Unit () const;
float Cross (const Vector2D param) const;
float Dot (const Vector2D param) const;
float Len () const;
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);
}
}
// Draw preview of insert point
if (mode == 4) {
Vector2D p1 = spline.GetClosestPoint(Vector2D(mx,my));
DrawCircle(p1.x,p1.y,4);
}
}