Implemented finding of nearest point to spline classes.
Originally committed to SVN as r1389.
This commit is contained in:
parent
ee832d642d
commit
14ade371f3
7 changed files with 137 additions and 32 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(); }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue