Visual typesetting vector clip now supports insertion of new points.

Originally committed to SVN as r1390.
This commit is contained in:
Rodrigo Braz Monteiro 2007-07-07 21:13:20 +00:00
parent 14ade371f3
commit 12534f74a7
5 changed files with 105 additions and 20 deletions

View File

@ -181,9 +181,26 @@ void Spline::DecodeFromASS(wxString str) {
////////////////////////////////
// Append a curve to the spline
void Spline::AppendCurve(SplineCurve &curve) {
curves.push_back(curve);
// Insert a curve to the spline
void Spline::InsertCurve(SplineCurve &curve,int index) {
if (index == -1) curves.push_back(curve);
else {
std::list<SplineCurve>::iterator cur;
int i=0;
for (cur=curves.begin();cur!=curves.end() && i < index;cur++,i++);
curves.insert(cur,curve);
}
}
////////////////////////
// Get a specific curve
SplineCurve *Spline::GetCurve(int index) {
int i=0;
for (std::list<SplineCurve>::iterator cur=curves.begin();cur!=curves.end() && i <= index;cur++,i++) {
if (i==index) return &(*cur);
}
return NULL;
}
@ -279,7 +296,7 @@ void Spline::GetPointList(std::vector<Vector2D> &points) {
int steps = len/8;
// Render curve
for (int i=0;i<steps;i++) {
for (int i=1;i<=steps;i++) {
// Get t and t-1 (u)
float t = float(i)/float(steps);
points.push_back(cur->GetPoint(t));

View File

@ -56,11 +56,13 @@ public:
wxString EncodeToASS();
void DecodeFromASS(wxString str);
void AppendCurve(SplineCurve &curve);
void AppendCurve(SplineCurve &curve) { InsertCurve(curve,-1); }
void InsertCurve(SplineCurve &curve,int index);
void MovePoint(int curveIndex,int point,wxPoint pos);
void Smooth(float smooth=1.0f);
void GetPointList(std::vector<Vector2D> &points);
SplineCurve *GetCurve(int index);
void GetClosestParametricPoint(Vector2D reference,int &curve,float &t,Vector2D &point);
Vector2D GetClosestPoint(Vector2D reference);

View File

@ -55,9 +55,9 @@ void SplineCurve::Split(SplineCurve &c1,SplineCurve &c2,float t) {
c1.type = CURVE_LINE;
c2.type = CURVE_LINE;
c1.p1 = p1;
c1.p2 = p1*t+p2*(1-t);
c2.p1 = c1.p2;
c2.p2 = p2;
c1.p2 = p1*(1-t)+p2*t;
c2.p1 = c1.p2;
}
// Split a bicubic
@ -67,22 +67,22 @@ void SplineCurve::Split(SplineCurve &c1,SplineCurve &c2,float t) {
// Sub-divisions
float u = 1-t;
Vector2D p12 = p1*t+p2*u;
Vector2D p23 = p2*t+p3*u;
Vector2D p34 = p3*t+p4*u;
Vector2D p123 = p12*t+p23*u;
Vector2D p234 = p23*t+p34*u;
Vector2D p1234 = p123*t+p234*u;
Vector2D p12 = p1*u+p2*t;
Vector2D p23 = p2*u+p3*t;
Vector2D p34 = p3*u+p4*t;
Vector2D p123 = p12*u+p23*t;
Vector2D p234 = p23*u+p34*t;
Vector2D p1234 = p123*u+p234*t;
// Set points
c1.p1 = p1;
c2.p4 = p4;
c1.p2 = p12;
c1.p3 = p123;
c1.p4 = p1234;
c2.p1 = p1234;
c2.p2 = p234;
c2.p3 = p34;
c2.p4 = p4;
}
}
@ -168,8 +168,7 @@ Vector2D SplineCurve::GetClosestPoint(Vector2D ref) const {
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);
return GetClosestSegmentPart(p1,p2,ref);
}
// Bicubic
@ -196,6 +195,32 @@ float SplineCurve::GetClosestParam(Vector2D ref) const {
//////////////////
// 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()));
// Bicubic
if (type == CURVE_BICUBIC) {
float len1 = GetClosestSegmentDistance(p1,p2,ref);
float len2 = GetClosestSegmentDistance(p2,p3,ref);
float len3 = GetClosestSegmentDistance(p3,p4,ref);
float len4 = GetClosestSegmentDistance(p4,p1,ref);
float len5 = GetClosestSegmentDistance(p1,p3,ref);
float len6 = GetClosestSegmentDistance(p2,p4,ref);
return MIN(MIN(MIN(len1,len2),MIN(len3,len4)),MIN(len5,len6));
}
// Something else
else return (GetClosestPoint(ref)-ref).Len();
}
//////////////////////////////////////////
// Closest t in segment p1-p2 to point p3
float SplineCurve::GetClosestSegmentPart(Vector2D pt1,Vector2D pt2,Vector2D pt3) const {
return MID(0.0f,(pt3-pt1).Dot(pt2-pt1)/(pt2-pt1).SquareLen(),1.0f);
}
/////////////////////////////////////////////////
// Closest distance between p3 and segment p1-p2
float SplineCurve::GetClosestSegmentDistance(Vector2D pt1,Vector2D pt2,Vector2D pt3) const {
float t = GetClosestSegmentPart(pt1,pt2,pt3);
return (pt1*(1.0f-t)+pt2*t-pt3).Len();
}

View File

@ -55,6 +55,10 @@ enum CurveType {
////////////////
// Spline curve
class SplineCurve {
private:
float GetClosestSegmentPart(Vector2D p1,Vector2D p2,Vector2D p3) const;
float GetClosestSegmentDistance(Vector2D p1,Vector2D p2,Vector2D p3) const;
public:
Vector2D p1,p2,p3,p4;
CurveType type;

View File

@ -289,7 +289,7 @@ void VisualToolVectorClip::ClickedFeature(VisualDraggableFeature &feature) {
/////////////
// Can hold?
bool VisualToolVectorClip::HoldEnabled() {
return mode == 1 || mode == 2 || mode == 6 || mode == 7;
return mode <= 4 || mode == 6 || mode == 7;
}
@ -320,8 +320,45 @@ void VisualToolVectorClip::InitializeHold() {
spline.AppendCurve(curve);
}
// Convert and insert
else if (mode == 3 || mode == 4) {
// Get closest point
Vector2D pt;
int curve;
float t;
spline.GetClosestParametricPoint(Vector2D(mx,my),curve,t,pt);
// Convert
if (mode == 3) {
}
// Insert
else {
// Split the curve
SplineCurve *c1 = spline.GetCurve(curve);
SplineCurve c2;
if (!c1) {
SplineCurve ct;
ct.type = CURVE_LINE;
ct.p1 = spline.curves.back().GetEndPoint();
ct.p2 = spline.curves.front().p1;
ct.p2 = ct.p1*(1-t) + ct.p2*t;
spline.AppendCurve(ct);
}
else {
c1->Split(*c1,c2,t);
spline.InsertCurve(c2,curve+1);
}
}
// Commit
SetOverride(_T("\\clip"),_T("(") + spline.EncodeToASS() + _T(")"));
Commit(true);
holding = false;
}
// Freehand
if (mode == 6 || mode == 7) {
else if (mode == 6 || mode == 7) {
spline.curves.clear();
lastX = -100000;
lastY = -100000;
@ -386,7 +423,7 @@ void VisualToolVectorClip::CommitHold() {
if (!holding && mode == 7) spline.Smooth();
// Save it
SetOverride(_T("\\clip"),_T("(") + spline.EncodeToASS() + _T(")"));
if (mode != 3 && mode != 4) SetOverride(_T("\\clip"),_T("(") + spline.EncodeToASS() + _T(")"));
}