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 // Insert a curve to the spline
void Spline::AppendCurve(SplineCurve &curve) { void Spline::InsertCurve(SplineCurve &curve,int index) {
curves.push_back(curve); 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; int steps = len/8;
// Render curve // Render curve
for (int i=0;i<steps;i++) { for (int i=1;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);
points.push_back(cur->GetPoint(t)); points.push_back(cur->GetPoint(t));

View file

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

View file

@ -55,9 +55,9 @@ void SplineCurve::Split(SplineCurve &c1,SplineCurve &c2,float t) {
c1.type = CURVE_LINE; c1.type = CURVE_LINE;
c2.type = CURVE_LINE; c2.type = CURVE_LINE;
c1.p1 = p1; c1.p1 = p1;
c1.p2 = p1*t+p2*(1-t);
c2.p1 = c1.p2;
c2.p2 = p2; c2.p2 = p2;
c1.p2 = p1*(1-t)+p2*t;
c2.p1 = c1.p2;
} }
// Split a bicubic // Split a bicubic
@ -67,22 +67,22 @@ void SplineCurve::Split(SplineCurve &c1,SplineCurve &c2,float t) {
// Sub-divisions // Sub-divisions
float u = 1-t; float u = 1-t;
Vector2D p12 = p1*t+p2*u; Vector2D p12 = p1*u+p2*t;
Vector2D p23 = p2*t+p3*u; Vector2D p23 = p2*u+p3*t;
Vector2D p34 = p3*t+p4*u; Vector2D p34 = p3*u+p4*t;
Vector2D p123 = p12*t+p23*u; Vector2D p123 = p12*u+p23*t;
Vector2D p234 = p23*t+p34*u; Vector2D p234 = p23*u+p34*t;
Vector2D p1234 = p123*t+p234*u; Vector2D p1234 = p123*u+p234*t;
// Set points // Set points
c1.p1 = p1; c1.p1 = p1;
c2.p4 = p4;
c1.p2 = p12; c1.p2 = p12;
c1.p3 = p123; c1.p3 = p123;
c1.p4 = p1234; c1.p4 = p1234;
c2.p1 = p1234; c2.p1 = p1234;
c2.p2 = p234; c2.p2 = p234;
c2.p3 = p34; c2.p3 = p34;
c2.p4 = p4;
} }
} }
@ -168,8 +168,7 @@ Vector2D SplineCurve::GetClosestPoint(Vector2D ref) const {
float SplineCurve::GetClosestParam(Vector2D ref) const { float SplineCurve::GetClosestParam(Vector2D ref) const {
// Line // Line
if (type == CURVE_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 GetClosestSegmentPart(p1,p2,ref);
return MID(0.0f,(ref-p1).Dot(p2-p1)/(p2-p1).SquareLen(),1.0f);
} }
// Bicubic // Bicubic
@ -196,6 +195,32 @@ float SplineCurve::GetClosestParam(Vector2D ref) const {
////////////////// //////////////////
// Quick distance // Quick distance
float SplineCurve::GetQuickDistance(Vector2D ref) const { 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(); 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 // Spline curve
class SplineCurve { class SplineCurve {
private:
float GetClosestSegmentPart(Vector2D p1,Vector2D p2,Vector2D p3) const;
float GetClosestSegmentDistance(Vector2D p1,Vector2D p2,Vector2D p3) const;
public: public:
Vector2D p1,p2,p3,p4; Vector2D p1,p2,p3,p4;
CurveType type; CurveType type;

View file

@ -289,7 +289,7 @@ void VisualToolVectorClip::ClickedFeature(VisualDraggableFeature &feature) {
///////////// /////////////
// Can hold? // Can hold?
bool VisualToolVectorClip::HoldEnabled() { 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); 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 // Freehand
if (mode == 6 || mode == 7) { else if (mode == 6 || mode == 7) {
spline.curves.clear(); spline.curves.clear();
lastX = -100000; lastX = -100000;
lastY = -100000; lastY = -100000;
@ -386,7 +423,7 @@ void VisualToolVectorClip::CommitHold() {
if (!holding && mode == 7) spline.Smooth(); if (!holding && mode == 7) spline.Smooth();
// Save it // Save it
SetOverride(_T("\\clip"),_T("(") + spline.EncodeToASS() + _T(")")); if (mode != 3 && mode != 4) SetOverride(_T("\\clip"),_T("(") + spline.EncodeToASS() + _T(")"));
} }