"SnapTo" feature enabled in the curve editor + non periodic handling of the flat curve editor.
Here is the new modifiew key behaviour : * CONTROL while dragging a point : slow down 20x the point move (i.e. 1pixel of cursor move move the control point by 0.05px) * SHIFT while dragging a point : snap the point to the following elements, on a "use nearest solution" method : o Diagonal curve editor : + top bound, + bottom bound, + identity (diagonal) line, + same Y than previous point, + same Y than next point, + line made by the previous and next point ; this will help to create linear parts in the curve more easilly o Flat curve editor (when moving a point) : + top bound, + bottom bound, + identity (horizontal) line, + same Y than previous point (or last point if you move the first point), + same Y than next point (or first point if you move the last point o Flat curve editor (when moving a tangential handle) : + 0.0, 0.35, 0.5, 1.0 values 0.35 is the default handles value and does create an smooth "diagonal" transition between points.
This commit is contained in:
@@ -264,12 +264,13 @@ class FlatCurve : public Curve {
|
|||||||
FlatCurveType kind;
|
FlatCurveType kind;
|
||||||
double* leftTangent;
|
double* leftTangent;
|
||||||
double* rightTangent;
|
double* rightTangent;
|
||||||
|
bool periodic;
|
||||||
|
|
||||||
void CtrlPoints_set ();
|
void CtrlPoints_set ();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FlatCurve (const std::vector<double>& points, int ppn=CURVES_MIN_POLY_POINTS);
|
FlatCurve (const std::vector<double>& points, bool isPeriodic = true, int ppn=CURVES_MIN_POLY_POINTS);
|
||||||
~FlatCurve ();
|
~FlatCurve ();
|
||||||
|
|
||||||
double getVal (double t);
|
double getVal (double t);
|
||||||
|
@@ -29,21 +29,24 @@
|
|||||||
|
|
||||||
namespace rtengine {
|
namespace rtengine {
|
||||||
|
|
||||||
FlatCurve::FlatCurve (const std::vector<double>& p, int poly_pn) : leftTangent(NULL), rightTangent(NULL) {
|
FlatCurve::FlatCurve (const std::vector<double>& p, bool isPeriodic, int poly_pn) : leftTangent(NULL), rightTangent(NULL) {
|
||||||
|
|
||||||
ppn = poly_pn;
|
ppn = poly_pn;
|
||||||
|
poly_x.clear();
|
||||||
|
poly_y.clear();
|
||||||
|
|
||||||
if (p.size()<5) {
|
|
||||||
kind = FCT_Empty;
|
kind = FCT_Empty;
|
||||||
}
|
periodic = isPeriodic;
|
||||||
else {
|
|
||||||
|
if (p.size()>4) {
|
||||||
kind = (FlatCurveType)p[0];
|
kind = (FlatCurveType)p[0];
|
||||||
if (kind==FCT_MinMaxCPoints) {
|
if (kind==FCT_MinMaxCPoints) {
|
||||||
|
int oneMorePoint = periodic ? 1:0;
|
||||||
N = (p.size()-1)/4;
|
N = (p.size()-1)/4;
|
||||||
x = new double[N+1];
|
x = new double[N+oneMorePoint];
|
||||||
y = new double[N+1];
|
y = new double[N+oneMorePoint];
|
||||||
leftTangent = new double[N+1];
|
leftTangent = new double[N+oneMorePoint];
|
||||||
rightTangent = new double[N+1];
|
rightTangent = new double[N+oneMorePoint];
|
||||||
int ix = 1;
|
int ix = 1;
|
||||||
for (int i=0; i<N; i++) {
|
for (int i=0; i<N; i++) {
|
||||||
x[i] = p[ix++];
|
x[i] = p[ix++];
|
||||||
@@ -52,11 +55,16 @@ FlatCurve::FlatCurve (const std::vector<double>& p, int poly_pn) : leftTangent(N
|
|||||||
rightTangent[i] = p[ix++];
|
rightTangent[i] = p[ix++];
|
||||||
}
|
}
|
||||||
// The first point is copied to the end of the point list, to handle the curve periodicity
|
// The first point is copied to the end of the point list, to handle the curve periodicity
|
||||||
|
if (periodic) {
|
||||||
x[N] = p[1]+1.0;
|
x[N] = p[1]+1.0;
|
||||||
y[N] = p[2];
|
y[N] = p[2];
|
||||||
leftTangent[N] = p[3];
|
leftTangent[N] = p[3];
|
||||||
rightTangent[N] = p[4];
|
rightTangent[N] = p[4];
|
||||||
if (N > 1)
|
}
|
||||||
|
else {
|
||||||
|
N--;
|
||||||
|
}
|
||||||
|
if (N > 0+(periodic?1:0) )
|
||||||
CtrlPoints_set ();
|
CtrlPoints_set ();
|
||||||
}
|
}
|
||||||
/*else if (kind==FCT_Parametric) {
|
/*else if (kind==FCT_Parametric) {
|
||||||
@@ -239,7 +247,13 @@ void FlatCurve::CtrlPoints_set () {
|
|||||||
poly_y.clear();
|
poly_y.clear();
|
||||||
j = 0;
|
j = 0;
|
||||||
|
|
||||||
// very first point of the curve
|
// adding an initial horizontal line if necessary
|
||||||
|
if (!periodic && sc_x[j] != 0.) {
|
||||||
|
poly_x.push_back(0.);
|
||||||
|
poly_y.push_back(sc_y[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the first point of the curves
|
||||||
poly_x.push_back(sc_x[j]);
|
poly_x.push_back(sc_x[j]);
|
||||||
poly_y.push_back(sc_y[j]);
|
poly_y.push_back(sc_y[j]);
|
||||||
|
|
||||||
@@ -256,7 +270,7 @@ void FlatCurve::CtrlPoints_set () {
|
|||||||
nbr_points = (int)(((double)(ppn) * sc_length[i] )/ total_length);
|
nbr_points = (int)(((double)(ppn) * sc_length[i] )/ total_length);
|
||||||
if (nbr_points<0){
|
if (nbr_points<0){
|
||||||
for(unsigned int it=0;it < sc_x.size(); it+=3) printf("sc_length[%d/3]=%f \n",it,sc_length[it/3]);
|
for(unsigned int it=0;it < sc_x.size(); it+=3) printf("sc_length[%d/3]=%f \n",it,sc_length[it/3]);
|
||||||
printf("Flat curve: error detected!\n i=%d nbr_points=%d ppn=%d N=%d sc_length[i/3]=%f total_length=%f",i,nbr_points,ppn,N,sc_length[i/3],total_length);
|
printf("Flat curve: error detected!\n i=%d periodic=%d nbr_points=%d ppn=%d N=%d sc_length[i/3]=%f total_length=%f",i,periodic,nbr_points,ppn,N,sc_length[i/3],total_length);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
// increment along the curve, not along the X axis
|
// increment along the curve, not along the X axis
|
||||||
@@ -268,6 +282,12 @@ void FlatCurve::CtrlPoints_set () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// adding an final horizontal line if necessary
|
||||||
|
if (!periodic && sc_x[--j] != 1.) {
|
||||||
|
poly_x.push_back(1.);
|
||||||
|
poly_y.push_back(sc_y[j]);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Checking the values
|
// Checking the values
|
||||||
Glib::ustring fname = "Curve.xyz"; // TopSolid'Design "plot" file format
|
Glib::ustring fname = "Curve.xyz"; // TopSolid'Design "plot" file format
|
||||||
|
@@ -56,7 +56,9 @@ std::vector<double> DiagonalCurveEditor::getCurve () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FlatCurveEditor::FlatCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup) : CurveEditor::CurveEditor(text, (CurveEditorGroup*) ceGroup, ceSubGroup) {
|
FlatCurveEditor::FlatCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup, bool isPeriodic) : CurveEditor::CurveEditor(text, (CurveEditorGroup*) ceGroup, ceSubGroup) {
|
||||||
|
|
||||||
|
periodic = isPeriodic;
|
||||||
|
|
||||||
// Order set in the same order than "enum FlatCurveType". Shouldn't change, for compatibility reason
|
// Order set in the same order than "enum FlatCurveType". Shouldn't change, for compatibility reason
|
||||||
curveType->addEntry(argv0+"/images/curveType-flatLinear.png", M("CURVEEDITOR_LINEAR")); // 0 Linear
|
curveType->addEntry(argv0+"/images/curveType-flatLinear.png", M("CURVEEDITOR_LINEAR")); // 0 Linear
|
||||||
|
@@ -110,9 +110,10 @@ class FlatCurveEditor : public CurveEditor {
|
|||||||
protected:
|
protected:
|
||||||
// reflects the buttonType active selection ; used as a pre-'selectionChange' reminder value
|
// reflects the buttonType active selection ; used as a pre-'selectionChange' reminder value
|
||||||
std::vector<double> controlPointsCurveEd;
|
std::vector<double> controlPointsCurveEd;
|
||||||
|
bool periodic;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FlatCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup);
|
FlatCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup, bool isPeriodic = true);
|
||||||
std::vector<double> getCurve ();
|
std::vector<double> getCurve ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -56,8 +56,10 @@ void CurveEditorGroup::hideCurrentCurve() {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a new curve to the curves list
|
* Add a new curve to the curves list
|
||||||
|
*
|
||||||
|
* The "periodic" parameter is only used by flat curve editors
|
||||||
*/
|
*/
|
||||||
CurveEditor* CurveEditorGroup::addCurve(CurveType cType, Glib::ustring curveLabel) {
|
CurveEditor* CurveEditorGroup::addCurve(CurveType cType, Glib::ustring curveLabel, bool periodic) {
|
||||||
switch (cType) {
|
switch (cType) {
|
||||||
case (CT_Diagonal):
|
case (CT_Diagonal):
|
||||||
if (!diagonalSubGroup) {
|
if (!diagonalSubGroup) {
|
||||||
@@ -68,7 +70,7 @@ CurveEditor* CurveEditorGroup::addCurve(CurveType cType, Glib::ustring curveLabe
|
|||||||
if (!flatSubGroup) {
|
if (!flatSubGroup) {
|
||||||
flatSubGroup = new FlatCurveEditorSubGroup(this);
|
flatSubGroup = new FlatCurveEditorSubGroup(this);
|
||||||
}
|
}
|
||||||
return (CurveEditor*)flatSubGroup->addCurve(curveLabel);
|
return (CurveEditor*)flatSubGroup->addCurve(curveLabel, periodic);
|
||||||
default:
|
default:
|
||||||
return (CurveEditor*)NULL;
|
return (CurveEditor*)NULL;
|
||||||
break;
|
break;
|
||||||
|
@@ -70,7 +70,7 @@ public:
|
|||||||
void setColorProvider (ColorProvider* p) { cp = p; }
|
void setColorProvider (ColorProvider* p) { cp = p; }
|
||||||
CurveEditor* getDisplayedCurve () { return displayedCurve; }
|
CurveEditor* getDisplayedCurve () { return displayedCurve; }
|
||||||
//void on_realize ();
|
//void on_realize ();
|
||||||
CurveEditor* addCurve(CurveType cType, Glib::ustring curveLabel);
|
CurveEditor* addCurve(CurveType cType, Glib::ustring curveLabel, bool periodic = true);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//void curveTypeToggled ();
|
//void curveTypeToggled ();
|
||||||
|
@@ -72,8 +72,8 @@ FlatCurveEditorSubGroup::~FlatCurveEditorSubGroup() {
|
|||||||
/*
|
/*
|
||||||
* Add a new curve to the curves list
|
* Add a new curve to the curves list
|
||||||
*/
|
*/
|
||||||
FlatCurveEditor* FlatCurveEditorSubGroup::addCurve(Glib::ustring curveLabel) {
|
FlatCurveEditor* FlatCurveEditorSubGroup::addCurve(Glib::ustring curveLabel, bool isPeriodic) {
|
||||||
FlatCurveEditor* newCE = new FlatCurveEditor(curveLabel, parent, this);
|
FlatCurveEditor* newCE = new FlatCurveEditor(curveLabel, parent, this, isPeriodic);
|
||||||
|
|
||||||
// Initialization of the new curve
|
// Initialization of the new curve
|
||||||
storeCurveValues(newCE, getCurveFromGUI(FCT_MinMaxCPoints));
|
storeCurveValues(newCE, getCurveFromGUI(FCT_MinMaxCPoints));
|
||||||
@@ -99,6 +99,7 @@ void FlatCurveEditorSubGroup::switchGUI() {
|
|||||||
|
|
||||||
switch((FlatCurveType)(dCurve->curveType->getSelected())) {
|
switch((FlatCurveType)(dCurve->curveType->getSelected())) {
|
||||||
case (FCT_MinMaxCPoints):
|
case (FCT_MinMaxCPoints):
|
||||||
|
CPointsCurve->setPeriodicity(dCurve->periodic); // Setting Periodicity before setting points
|
||||||
CPointsCurve->setPoints (dCurve->controlPointsCurveEd);
|
CPointsCurve->setPoints (dCurve->controlPointsCurveEd);
|
||||||
parent->pack_start (*CPointsCurveBox);
|
parent->pack_start (*CPointsCurveBox);
|
||||||
CPointsCurveBox->check_resize();
|
CPointsCurveBox->check_resize();
|
||||||
|
@@ -40,7 +40,7 @@ public:
|
|||||||
FlatCurveEditorSubGroup(CurveEditorGroup* prt);
|
FlatCurveEditorSubGroup(CurveEditorGroup* prt);
|
||||||
~FlatCurveEditorSubGroup();
|
~FlatCurveEditorSubGroup();
|
||||||
|
|
||||||
FlatCurveEditor* addCurve(Glib::ustring curveLabel = "");
|
FlatCurveEditor* addCurve(Glib::ustring curveLabel = "", bool periodic = true);
|
||||||
//virtual void updateBackgroundHistogram (CurveEditor* ce);
|
//virtual void updateBackgroundHistogram (CurveEditor* ce);
|
||||||
virtual void setColorProvider (ColorProvider* p);
|
virtual void setColorProvider (ColorProvider* p);
|
||||||
|
|
||||||
|
@@ -31,6 +31,7 @@ MyCurve::MyCurve () : listener(NULL) {
|
|||||||
snapTo = ST_None;
|
snapTo = ST_None;
|
||||||
colorProvider = NULL;
|
colorProvider = NULL;
|
||||||
sized = RS_Pending;
|
sized = RS_Pending;
|
||||||
|
snapToElmt = -100;
|
||||||
|
|
||||||
set_extension_events(Gdk::EXTENSION_EVENTS_ALL);
|
set_extension_events(Gdk::EXTENSION_EVENTS_ALL);
|
||||||
add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON1_MOTION_MASK);
|
add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON1_MOTION_MASK);
|
||||||
@@ -54,3 +55,16 @@ void MyCurve::notifyListener () {
|
|||||||
if (listener)
|
if (listener)
|
||||||
listener->curveChanged ();
|
listener->curveChanged ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MyCurve::snapCoordinate(double testedVal, double realVal) {
|
||||||
|
|
||||||
|
double distY = realVal - testedVal;
|
||||||
|
|
||||||
|
if (distY < 0.) distY = -distY;
|
||||||
|
if (distY < snapToMinDist) {
|
||||||
|
snapToMinDist = distY;
|
||||||
|
snapToVal = testedVal;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@@ -70,12 +70,25 @@ class MyCurve : public Gtk::DrawingArea {
|
|||||||
std::vector<Gdk::Point> upoint;
|
std::vector<Gdk::Point> upoint;
|
||||||
std::vector<Gdk::Point> lpoint;
|
std::vector<Gdk::Point> lpoint;
|
||||||
bool buttonPressed;
|
bool buttonPressed;
|
||||||
enum SnapToType snapTo;
|
/*
|
||||||
|
* snapToElmt must be interpreted like this:
|
||||||
|
* -100 : no element (default)
|
||||||
|
* -3 : maximum value
|
||||||
|
* -2 : identity value
|
||||||
|
* -1 : minimum value
|
||||||
|
* [0;1000[ : control point that it's snapped to
|
||||||
|
* >=1000 : moved control point which is snapped to to the line made by it neighbors
|
||||||
|
*/
|
||||||
|
int snapToElmt;
|
||||||
|
bool snapTo;
|
||||||
|
double snapToMinDist;
|
||||||
|
double snapToVal;
|
||||||
MyCurveIdleHelper* mcih;
|
MyCurveIdleHelper* mcih;
|
||||||
enum ResizeState sized;
|
enum ResizeState sized;
|
||||||
|
|
||||||
virtual std::vector<double> get_vector (int veclen) = 0;
|
virtual std::vector<double> get_vector (int veclen) = 0;
|
||||||
int getGraphMinSize() { return GRAPH_SIZE + RADIUS + 1; }
|
int getGraphMinSize() { return GRAPH_SIZE + RADIUS + 1; }
|
||||||
|
bool snapCoordinate(double testedVal, double realVal);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MyCurve ();
|
MyCurve ();
|
||||||
|
@@ -178,6 +178,9 @@ void MyDiagonalCurve::draw (int handle) {
|
|||||||
cr->stroke ();
|
cr->stroke ();
|
||||||
|
|
||||||
// draw f(x)=x line
|
// draw f(x)=x line
|
||||||
|
if (snapToElmt == -2)
|
||||||
|
cr->set_source_rgb (1.0, 0.0, 0.0);
|
||||||
|
else
|
||||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||||
std::valarray<double> ds (1);
|
std::valarray<double> ds (1);
|
||||||
ds[0] = 4;
|
ds[0] = 4;
|
||||||
@@ -205,20 +208,30 @@ void MyDiagonalCurve::draw (int handle) {
|
|||||||
|
|
||||||
// draw the cage of the NURBS curve
|
// draw the cage of the NURBS curve
|
||||||
if (curve.type==DCT_NURBS) {
|
if (curve.type==DCT_NURBS) {
|
||||||
|
unsigned int nbPoints;
|
||||||
std::valarray<double> ch_ds (1);
|
std::valarray<double> ch_ds (1);
|
||||||
ch_ds[0] = 2;
|
ch_ds[0] = 2;
|
||||||
cr->set_dash (ch_ds, 0);
|
cr->set_dash (ch_ds, 0);
|
||||||
cr->set_source_rgb (0.0, 0.0, 0.0);
|
cr->set_source_rgb (0.0, 0.0, 0.0);
|
||||||
std::vector<double> points = getPoints();
|
std::vector<double> points = getPoints();
|
||||||
for (int i = 1; i < (int)points.size(); ) {
|
nbPoints = ((int)points.size()-1)/2;
|
||||||
double x = ((innerWidth-1) * points[i++] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, innerWidth);
|
for (unsigned int i = 1; i < nbPoints; i++) {
|
||||||
double y = innerHeight - ((innerHeight-1) * points[i++] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, innerHeight);
|
int pos = i*2+1;
|
||||||
if (i==3)
|
|
||||||
cr->move_to (x, y);
|
double x1 = ((innerWidth-1) * points[pos-2] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, innerWidth);
|
||||||
|
double y1 = innerHeight - ((innerHeight-1) * points[pos-1] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, innerHeight);
|
||||||
|
double x2 = ((innerWidth-1) * points[pos] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, innerWidth);
|
||||||
|
double y2 = innerHeight - ((innerHeight-1) * points[pos+1] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, innerHeight);
|
||||||
|
|
||||||
|
// set the color of the line when the point is snapped to the cage
|
||||||
|
if (curve.x.size() == nbPoints && snapToElmt >= 1000 && ((i == (snapToElmt-1000)) || (i == (snapToElmt-999))))
|
||||||
|
cr->set_source_rgb (1.0, 0.0, 0.0);
|
||||||
else
|
else
|
||||||
cr->line_to (x, y);
|
cr->set_source_rgb (0.0, 0.0, 0.0);
|
||||||
}
|
cr->move_to (x1, y1);
|
||||||
|
cr->line_to (x2, y2);
|
||||||
cr->stroke ();
|
cr->stroke ();
|
||||||
|
}
|
||||||
cr->unset_dash ();
|
cr->unset_dash ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,7 +245,17 @@ void MyDiagonalCurve::draw (int handle) {
|
|||||||
// draw bullets
|
// draw bullets
|
||||||
if (curve.type!=DCT_Parametric)
|
if (curve.type!=DCT_Parametric)
|
||||||
for (int i = 0; i < (int)curve.x.size(); ++i) {
|
for (int i = 0; i < (int)curve.x.size(); ++i) {
|
||||||
cr->set_source_rgb ((i == handle ? 1.0 : 0.0), 0.0, 0.0);
|
if (curve.x[i] == -1) continue;
|
||||||
|
if (snapToElmt >= 1000) {
|
||||||
|
int pt = snapToElmt-1000;
|
||||||
|
if (i >= (pt-1) && i <= (pt+1))
|
||||||
|
cr->set_source_rgb(1.0, 0.0, 0.0);
|
||||||
|
else
|
||||||
|
cr->set_source_rgb(0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cr->set_source_rgb ((i == handle || i == snapToElmt ? 1.0 : 0.0), 0.0, 0.0);
|
||||||
|
|
||||||
double x = ((innerWidth-1) * curve.x[i] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, innerWidth);
|
double x = ((innerWidth-1) * curve.x[i] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, innerWidth);
|
||||||
double y = innerHeight - ((innerHeight-1) * curve.y[i] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, innerHeight);
|
double y = innerHeight - ((innerHeight-1) * curve.y[i] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, innerHeight);
|
||||||
|
|
||||||
@@ -297,6 +320,7 @@ bool MyDiagonalCurve::handleEvents (GdkEvent* event) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Gdk::BUTTON_PRESS:
|
case Gdk::BUTTON_PRESS:
|
||||||
|
snapToElmt = -100;
|
||||||
if (curve.type!=DCT_Parametric) {
|
if (curve.type!=DCT_Parametric) {
|
||||||
if (event->button.button == 1) {
|
if (event->button.button == 1) {
|
||||||
buttonPressed = true;
|
buttonPressed = true;
|
||||||
@@ -338,6 +362,7 @@ bool MyDiagonalCurve::handleEvents (GdkEvent* event) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Gdk::BUTTON_RELEASE:
|
case Gdk::BUTTON_RELEASE:
|
||||||
|
snapToElmt = -100;
|
||||||
if (curve.type!=DCT_Parametric) {
|
if (curve.type!=DCT_Parametric) {
|
||||||
if (buttonPressed && event->button.button == 1) {
|
if (buttonPressed && event->button.button == 1) {
|
||||||
buttonPressed = false;
|
buttonPressed = false;
|
||||||
@@ -398,7 +423,13 @@ bool MyDiagonalCurve::handleEvents (GdkEvent* event) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Gdk::MOTION_NOTIFY:
|
case Gdk::MOTION_NOTIFY:
|
||||||
|
snapToElmt = -100;
|
||||||
if (curve.type == DCT_Linear || curve.type == DCT_Spline || curve.type == DCT_NURBS) {
|
if (curve.type == DCT_Linear || curve.type == DCT_Spline || curve.type == DCT_NURBS) {
|
||||||
|
|
||||||
|
snapToMinDist = 10.;
|
||||||
|
snapToVal = 0.;
|
||||||
|
snapToElmt = -100;
|
||||||
|
|
||||||
// get the pointer position
|
// get the pointer position
|
||||||
getCursorPosition(event);
|
getCursorPosition(event);
|
||||||
|
|
||||||
@@ -439,6 +470,9 @@ bool MyDiagonalCurve::handleEvents (GdkEvent* event) {
|
|||||||
ugpX += deltaX;
|
ugpX += deltaX;
|
||||||
ugpY += deltaY;
|
ugpY += deltaY;
|
||||||
|
|
||||||
|
// the unclamped grabbed point is brought back in the range when snapTo is active
|
||||||
|
if (snapTo) ugpY = CLAMP(ugpY, 0.0, 1.0);
|
||||||
|
|
||||||
// handling limitations along X axis
|
// handling limitations along X axis
|
||||||
if (ugpX >= rightDeletionBound && (grab_point > 0 && grab_point < (num-1))) {
|
if (ugpX >= rightDeletionBound && (grab_point > 0 && grab_point < (num-1))) {
|
||||||
curve.x[grab_point] = -1.;
|
curve.x[grab_point] = -1.;
|
||||||
@@ -457,9 +491,39 @@ bool MyDiagonalCurve::handleEvents (GdkEvent* event) {
|
|||||||
else if (ugpY <= bottomDeletionBound && grab_point != 0 && grab_point != num-1) {
|
else if (ugpY <= bottomDeletionBound && grab_point != 0 && grab_point != num-1) {
|
||||||
curve.x[grab_point] = -1.;
|
curve.x[grab_point] = -1.;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
// snapping point to specific values
|
||||||
|
if (snapTo && curve.x[grab_point] != -1.) {
|
||||||
|
if (grab_point > 0 && grab_point < (curve.y.size()-1)) {
|
||||||
|
double prevX = curve.x[grab_point-1];
|
||||||
|
double prevY = curve.y[grab_point-1];
|
||||||
|
double nextX = curve.x[grab_point+1];
|
||||||
|
double nextY = curve.y[grab_point+1];
|
||||||
|
|
||||||
|
double ratio = (curve.x[grab_point]-prevX)/(nextX-prevX);
|
||||||
|
double y = (nextY-prevY) * ratio + prevY;
|
||||||
|
|
||||||
|
if (snapCoordinate(y, ugpY)) snapToElmt = 1000+grab_point;
|
||||||
|
}
|
||||||
|
if (grab_point > 0) {
|
||||||
|
int prevP = grab_point-1;
|
||||||
|
if (snapCoordinate(curve.y[prevP], ugpY)) snapToElmt = prevP;
|
||||||
|
}
|
||||||
|
if (grab_point < (curve.y.size()-1)) {
|
||||||
|
int nextP = grab_point+1;
|
||||||
|
if (snapCoordinate(curve.y[nextP], ugpY)) snapToElmt = nextP;
|
||||||
|
}
|
||||||
|
if (snapCoordinate(1.0, ugpY)) snapToElmt = -3;
|
||||||
|
if (snapCoordinate(curve.x[grab_point], ugpY)) snapToElmt = -2;
|
||||||
|
if (snapCoordinate(0.0, ugpY)) snapToElmt = -1;
|
||||||
|
|
||||||
|
curve.y[grab_point] = snapToVal;
|
||||||
|
}
|
||||||
|
else {
|
||||||
// nextPosY is in the bounds
|
// nextPosY is in the bounds
|
||||||
curve.y[grab_point] = CLAMP(ugpY, 0.0, 1.0);
|
curve.y[grab_point] = CLAMP(ugpY, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (curve.x[grab_point] != prevPosX || curve.y[grab_point] != prevPosY) {
|
if (curve.x[grab_point] != prevPosX || curve.y[grab_point] != prevPosY) {
|
||||||
// we recalculate the curve only if we have to
|
// we recalculate the curve only if we have to
|
||||||
@@ -529,9 +593,8 @@ void MyDiagonalCurve::getCursorPosition(GdkEvent* event) {
|
|||||||
int shift_key = mod_type & GDK_SHIFT_MASK;
|
int shift_key = mod_type & GDK_SHIFT_MASK;
|
||||||
|
|
||||||
// the increment get smaller if modifier key are used, and "snap to" may be enabled
|
// the increment get smaller if modifier key are used, and "snap to" may be enabled
|
||||||
if (control_key && shift_key) { snapTo = ST_Neighbors; }
|
if (control_key) { incrementX *= 0.05; incrementY *= 0.05; }
|
||||||
else if (control_key) { snapTo = ST_Identity; }
|
if (shift_key) { snapTo = true; }
|
||||||
else if (shift_key) { incrementX *= 0.04; incrementY *= 0.04; }
|
|
||||||
|
|
||||||
deltaX = (double)(cursorX - prevCursorX) * incrementX;
|
deltaX = (double)(cursorX - prevCursorX) * incrementX;
|
||||||
deltaY = (double)(cursorY - prevCursorY) * incrementY;
|
deltaY = (double)(cursorY - prevCursorY) * incrementY;
|
||||||
|
@@ -54,7 +54,7 @@ std::vector<double> MyFlatCurve::get_vector (int veclen) {
|
|||||||
|
|
||||||
// Get the curve control points
|
// Get the curve control points
|
||||||
std::vector<double> curveDescr = getPoints ();
|
std::vector<double> curveDescr = getPoints ();
|
||||||
rtengine::FlatCurve* rtcurve = new rtengine::FlatCurve (curveDescr, veclen*1.5 > 5000 ? 5000 : veclen*1.5);
|
rtengine::FlatCurve* rtcurve = new rtengine::FlatCurve (curveDescr, periodic, veclen*1.5 > 5000 ? 5000 : veclen*1.5);
|
||||||
|
|
||||||
// Create the sample values that will be converted
|
// Create the sample values that will be converted
|
||||||
std::vector<double> samples;
|
std::vector<double> samples;
|
||||||
@@ -157,13 +157,20 @@ void MyFlatCurve::draw () {
|
|||||||
double y0 = (double)RADIUS-0.5;
|
double y0 = (double)RADIUS-0.5;
|
||||||
double y1 = (double)RADIUS-0.5 + (double)innerHeight + 2.;
|
double y1 = (double)RADIUS-0.5 + (double)innerHeight + 2.;
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
|
cr->move_to (x0, y0);
|
||||||
|
cr->line_to (x0, y1);
|
||||||
|
cr->line_to (x1, y1);
|
||||||
|
cr->line_to (x1, y0);
|
||||||
|
cr->line_to (x0, y0);
|
||||||
|
}
|
||||||
|
/*for (int i = 0; i < 5; i++) {
|
||||||
double currX = (double)RADIUS-0.5 + (double)i*((double)innerWidth + 2.)/4.;
|
double currX = (double)RADIUS-0.5 + (double)i*((double)innerWidth + 2.)/4.;
|
||||||
double currY = (double)RADIUS-0.5 + (double)i*((double)innerHeight + 2.)/4.;
|
double currY = (double)RADIUS-0.5 + (double)i*((double)innerHeight + 2.)/4.;
|
||||||
cr->move_to (x0, currY);
|
cr->move_to (x0, currY);
|
||||||
cr->line_to (x1, currY);
|
cr->line_to (x1, currY);
|
||||||
cr->move_to (currX, y0);
|
cr->move_to (currX, y0);
|
||||||
cr->line_to (currX, y1);
|
cr->line_to (currX, y1);
|
||||||
}
|
}*/
|
||||||
cr->stroke ();
|
cr->stroke ();
|
||||||
|
|
||||||
// draw f(x)=0.5 line
|
// draw f(x)=0.5 line
|
||||||
@@ -171,13 +178,14 @@ void MyFlatCurve::draw () {
|
|||||||
std::valarray<double> ds (1);
|
std::valarray<double> ds (1);
|
||||||
ds[0] = 4;
|
ds[0] = 4;
|
||||||
cr->set_dash (ds, 0);
|
cr->set_dash (ds, 0);
|
||||||
cr->move_to ((double)RADIUS+0.5 , (double)RADIUS+0.5 + (double)innerHeight/2.);
|
cr->move_to (x0, (double)RADIUS+0.5 + (double)innerHeight/2.);
|
||||||
cr->line_to ((double)RADIUS+0.5 + (double)innerWidth/2., (double)RADIUS+0.5 + (double)innerHeight/2.);
|
cr->line_to (x1, (double)RADIUS+0.5 + (double)innerHeight/2.);
|
||||||
cr->stroke ();
|
cr->stroke ();
|
||||||
|
|
||||||
|
cr->unset_dash ();
|
||||||
|
|
||||||
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
||||||
|
|
||||||
cr->unset_dash ();
|
|
||||||
cr->set_line_width (1.0);
|
cr->set_line_width (1.0);
|
||||||
|
|
||||||
// draw the color feedback of the control points
|
// draw the color feedback of the control points
|
||||||
@@ -347,6 +355,9 @@ void MyFlatCurve::draw () {
|
|||||||
else
|
else
|
||||||
cr->set_source_rgb (1.0, 0.0, 0.0);
|
cr->set_source_rgb (1.0, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
|
else if (i == snapToElmt) {
|
||||||
|
cr->set_source_rgb (1.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
else if (curve.y[i] == 0.5)
|
else if (curve.y[i] == 0.5)
|
||||||
cr->set_source_rgb (0.0, 0.5, 0.0);
|
cr->set_source_rgb (0.0, 0.5, 0.0);
|
||||||
else
|
else
|
||||||
@@ -473,6 +484,7 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) {
|
|||||||
int src, dst;
|
int src, dst;
|
||||||
std::vector<double>::iterator itx, ity, itlt, itrt;
|
std::vector<double>::iterator itx, ity, itlt, itrt;
|
||||||
|
|
||||||
|
snapToElmt = -100;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
int num = (int)curve.x.size();
|
int num = (int)curve.x.size();
|
||||||
|
|
||||||
@@ -548,7 +560,7 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) {
|
|||||||
curve.rightTangent.insert (itrt, 0);
|
curve.rightTangent.insert (itrt, 0);
|
||||||
num++;
|
num++;
|
||||||
|
|
||||||
// the graph is refreshed only if a new point is created (snaped to a pixel)
|
// the graph is refreshed only if a new point is created
|
||||||
curve.x[closest_point] = clampedX;
|
curve.x[closest_point] = clampedX;
|
||||||
curve.y[closest_point] = clampedY;
|
curve.y[closest_point] = clampedY;
|
||||||
curve.leftTangent[closest_point] = 0.35;
|
curve.leftTangent[closest_point] = 0.35;
|
||||||
@@ -695,14 +707,13 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) {
|
|||||||
case Gdk::MOTION_NOTIFY:
|
case Gdk::MOTION_NOTIFY:
|
||||||
if (curve.type == FCT_Linear || curve.type == FCT_MinMaxCPoints) {
|
if (curve.type == FCT_Linear || curve.type == FCT_MinMaxCPoints) {
|
||||||
|
|
||||||
int leftNeigborPoint = -1;
|
|
||||||
int rightNeigborPoint = -1;
|
|
||||||
double leftNeigborY = -1.;
|
|
||||||
double rightNeigborY = -1.;
|
|
||||||
|
|
||||||
int previous_lit_point = lit_point;
|
int previous_lit_point = lit_point;
|
||||||
enum MouseOverAreas prevArea = area;
|
enum MouseOverAreas prevArea = area;
|
||||||
|
|
||||||
|
snapToMinDist = 10.;
|
||||||
|
snapToVal = 0.;
|
||||||
|
snapToElmt = -100;
|
||||||
|
|
||||||
// get the pointer position
|
// get the pointer position
|
||||||
getCursorPosition(event);
|
getCursorPosition(event);
|
||||||
getMouseOverArea();
|
getMouseOverArea();
|
||||||
@@ -826,13 +837,22 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case (FCT_EditedHandle_LeftTan): {
|
case (FCT_EditedHandle_LeftTan): {
|
||||||
double prevValue = ugpX;
|
double prevValue = curve.leftTangent[lit_point];
|
||||||
|
|
||||||
ugpX -= deltaX*3;
|
ugpX -= deltaX*3;
|
||||||
ugpX = CLAMP(ugpX, 0., 1.);
|
ugpX = CLAMP(ugpX, 0., 1.);
|
||||||
|
if (snapTo) {
|
||||||
|
snapCoordinate(0.0, ugpX);
|
||||||
|
snapCoordinate(0.35, ugpX);
|
||||||
|
snapCoordinate(0.5, ugpX);
|
||||||
|
snapCoordinate(1.0, ugpX);
|
||||||
|
curve.leftTangent[lit_point] = snapToVal;
|
||||||
|
}
|
||||||
|
else {
|
||||||
curve.leftTangent[lit_point] = ugpX;
|
curve.leftTangent[lit_point] = ugpX;
|
||||||
|
}
|
||||||
|
|
||||||
if (ugpX != prevValue) {
|
if (curve.leftTangent[lit_point] != prevValue) {
|
||||||
interpolate ();
|
interpolate ();
|
||||||
draw ();
|
draw ();
|
||||||
notifyListener ();
|
notifyListener ();
|
||||||
@@ -841,13 +861,22 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case (FCT_EditedHandle_RightTan): {
|
case (FCT_EditedHandle_RightTan): {
|
||||||
double prevValue = ugpX;
|
double prevValue = curve.rightTangent[lit_point];
|
||||||
|
|
||||||
ugpX += deltaX*3;
|
ugpX += deltaX*3;
|
||||||
ugpX = CLAMP(ugpX, 0., 1.);
|
ugpX = CLAMP(ugpX, 0., 1.);
|
||||||
|
if (snapTo) {
|
||||||
|
snapCoordinate(0.0, ugpX);
|
||||||
|
snapCoordinate(0.35, ugpX);
|
||||||
|
snapCoordinate(0.5, ugpX);
|
||||||
|
snapCoordinate(1.0, ugpX);
|
||||||
|
curve.rightTangent[lit_point] = snapToVal;
|
||||||
|
}
|
||||||
|
else {
|
||||||
curve.rightTangent[lit_point] = ugpX;
|
curve.rightTangent[lit_point] = ugpX;
|
||||||
|
}
|
||||||
|
|
||||||
if (ugpX != prevValue) {
|
if (curve.rightTangent[lit_point] != prevValue) {
|
||||||
interpolate ();
|
interpolate ();
|
||||||
draw ();
|
draw ();
|
||||||
notifyListener ();
|
notifyListener ();
|
||||||
@@ -855,7 +884,7 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// already process before the "switch" instruction
|
// already processed before the "switch" instruction
|
||||||
//case (FCT_EditedHandle_CPointUD):
|
//case (FCT_EditedHandle_CPointUD):
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -995,9 +1024,41 @@ void MyFlatCurve::movePoint(bool moveX, bool moveY) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (moveY) {
|
if (moveY) {
|
||||||
|
|
||||||
// we memorize the previous position of the point, for optimization purpose
|
// we memorize the previous position of the point, for optimization purpose
|
||||||
ugpY += deltaY;
|
ugpY += deltaY;
|
||||||
|
|
||||||
|
// snapping point to specific values
|
||||||
|
if (snapTo && curve.x[lit_point] != -1) {
|
||||||
|
|
||||||
|
// the unclamped grabbed point is brought back in the range
|
||||||
|
ugpY = CLAMP(ugpY, 0.0, 1.0);
|
||||||
|
|
||||||
|
if (lit_point == 0) {
|
||||||
|
int prevP = curve.y.size()-1;
|
||||||
|
if (snapCoordinate(curve.y[prevP], ugpY)) snapToElmt = prevP;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int prevP = lit_point-1;
|
||||||
|
if (snapCoordinate(curve.y[prevP], ugpY)) snapToElmt = prevP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curve.y.size() > 2) {
|
||||||
|
if (lit_point == (curve.y.size()-1)) {
|
||||||
|
if (snapCoordinate(curve.y[0], ugpY)) snapToElmt = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int nextP = lit_point+1;
|
||||||
|
if (snapCoordinate(curve.y[nextP], ugpY)) snapToElmt = nextP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (snapCoordinate(1.0, ugpY)) snapToElmt = -3;
|
||||||
|
if (snapCoordinate(0.5, ugpY)) snapToElmt = -2;
|
||||||
|
if (snapCoordinate(0.0, ugpY)) snapToElmt = -1;
|
||||||
|
|
||||||
|
curve.y[lit_point] = snapToVal;
|
||||||
|
}
|
||||||
|
|
||||||
// Handling limitations along Y axis
|
// Handling limitations along Y axis
|
||||||
if (ugpY >= topDeletionBound && nbPoints>2) {
|
if (ugpY >= topDeletionBound && nbPoints>2) {
|
||||||
if (curve.x[lit_point] != -1.) {
|
if (curve.x[lit_point] != -1.) {
|
||||||
@@ -1015,7 +1076,7 @@ void MyFlatCurve::movePoint(bool moveX, bool moveY) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// nextPosY is in the bounds
|
// nextPosY is in the bounds
|
||||||
curve.y[lit_point] = CLAMP(ugpY, 0.0, 1.0);
|
if (!snapTo) curve.y[lit_point] = CLAMP(ugpY, 0.0, 1.0);
|
||||||
if (!moveX && curve.x[lit_point] == -1.) {
|
if (!moveX && curve.x[lit_point] == -1.) {
|
||||||
// bring back the X value of the point if it reappear
|
// bring back the X value of the point if it reappear
|
||||||
curve.x[lit_point] = deletedPointX;
|
curve.x[lit_point] = deletedPointX;
|
||||||
@@ -1024,7 +1085,7 @@ void MyFlatCurve::movePoint(bool moveX, bool moveY) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (curve.x[lit_point] != prevPosX || curve.y[lit_point] != prevPosY) {
|
if (curve.x[lit_point] != prevPosX || curve.y[lit_point] != prevPosY) {
|
||||||
// we recalculate the curve only if we have to
|
// we recompute the curve only if we have to
|
||||||
interpolate ();
|
interpolate ();
|
||||||
draw ();
|
draw ();
|
||||||
notifyListener ();
|
notifyListener ();
|
||||||
@@ -1071,7 +1132,7 @@ void MyFlatCurve::getCursorPosition(GdkEvent* event) {
|
|||||||
preciseCursorX = cursorX * incrementX;
|
preciseCursorX = cursorX * incrementX;
|
||||||
preciseCursorY = cursorY * incrementY;
|
preciseCursorY = cursorY * incrementY;
|
||||||
|
|
||||||
snapTo = ST_None;
|
snapTo = false;
|
||||||
|
|
||||||
// update deltaX/Y if the user drags a point
|
// update deltaX/Y if the user drags a point
|
||||||
if (editedHandle != FCT_EditedHandle_None) {
|
if (editedHandle != FCT_EditedHandle_None) {
|
||||||
@@ -1080,9 +1141,8 @@ void MyFlatCurve::getCursorPosition(GdkEvent* event) {
|
|||||||
int shift_key = mod_type & GDK_SHIFT_MASK;
|
int shift_key = mod_type & GDK_SHIFT_MASK;
|
||||||
|
|
||||||
// the increment get smaller if modifier key are used, and "snap to" may be enabled
|
// the increment get smaller if modifier key are used, and "snap to" may be enabled
|
||||||
if (control_key && shift_key) { snapTo = ST_Neighbors; }
|
if (control_key) { incrementX *= 0.05; incrementY *= 0.05; }
|
||||||
else if (control_key) { snapTo = ST_Identity; }
|
if (shift_key) { snapTo = true; }
|
||||||
else if (shift_key) { incrementX *= 0.04; incrementY *= 0.04; }
|
|
||||||
|
|
||||||
deltaX = (double)(cursorX - prevCursorX) * incrementX;
|
deltaX = (double)(cursorX - prevCursorX) * incrementX;
|
||||||
deltaY = (double)(cursorY - prevCursorY) * incrementY;
|
deltaY = (double)(cursorY - prevCursorY) * incrementY;
|
||||||
|
@@ -114,6 +114,7 @@ class MyFlatCurve : public MyCurve {
|
|||||||
MyFlatCurve ();
|
MyFlatCurve ();
|
||||||
//~MyFlatCurve ();
|
//~MyFlatCurve ();
|
||||||
std::vector<double> getPoints ();
|
std::vector<double> getPoints ();
|
||||||
|
void setPeriodicity (bool isPeriodic) { periodic = isPeriodic; };
|
||||||
void setPoints (const std::vector<double>& p);
|
void setPoints (const std::vector<double>& p);
|
||||||
void setType (FlatCurveType t);
|
void setType (FlatCurveType t);
|
||||||
bool handleEvents (GdkEvent* event);
|
bool handleEvents (GdkEvent* event);
|
||||||
|
Reference in New Issue
Block a user