"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;
|
||||
double* leftTangent;
|
||||
double* rightTangent;
|
||||
bool periodic;
|
||||
|
||||
void CtrlPoints_set ();
|
||||
|
||||
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 ();
|
||||
|
||||
double getVal (double t);
|
||||
|
@@ -29,21 +29,24 @@
|
||||
|
||||
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;
|
||||
poly_x.clear();
|
||||
poly_y.clear();
|
||||
|
||||
if (p.size()<5) {
|
||||
kind = FCT_Empty;
|
||||
}
|
||||
else {
|
||||
kind = FCT_Empty;
|
||||
periodic = isPeriodic;
|
||||
|
||||
if (p.size()>4) {
|
||||
kind = (FlatCurveType)p[0];
|
||||
if (kind==FCT_MinMaxCPoints) {
|
||||
int oneMorePoint = periodic ? 1:0;
|
||||
N = (p.size()-1)/4;
|
||||
x = new double[N+1];
|
||||
y = new double[N+1];
|
||||
leftTangent = new double[N+1];
|
||||
rightTangent = new double[N+1];
|
||||
x = new double[N+oneMorePoint];
|
||||
y = new double[N+oneMorePoint];
|
||||
leftTangent = new double[N+oneMorePoint];
|
||||
rightTangent = new double[N+oneMorePoint];
|
||||
int ix = 1;
|
||||
for (int i=0; i<N; i++) {
|
||||
x[i] = p[ix++];
|
||||
@@ -52,11 +55,16 @@ FlatCurve::FlatCurve (const std::vector<double>& p, int poly_pn) : leftTangent(N
|
||||
rightTangent[i] = p[ix++];
|
||||
}
|
||||
// The first point is copied to the end of the point list, to handle the curve periodicity
|
||||
x[N] = p[1]+1.0;
|
||||
y[N] = p[2];
|
||||
leftTangent[N] = p[3];
|
||||
rightTangent[N] = p[4];
|
||||
if (N > 1)
|
||||
if (periodic) {
|
||||
x[N] = p[1]+1.0;
|
||||
y[N] = p[2];
|
||||
leftTangent[N] = p[3];
|
||||
rightTangent[N] = p[4];
|
||||
}
|
||||
else {
|
||||
N--;
|
||||
}
|
||||
if (N > 0+(periodic?1:0) )
|
||||
CtrlPoints_set ();
|
||||
}
|
||||
/*else if (kind==FCT_Parametric) {
|
||||
@@ -239,24 +247,30 @@ void FlatCurve::CtrlPoints_set () {
|
||||
poly_y.clear();
|
||||
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_y.push_back(sc_y[j]);
|
||||
|
||||
firstPointIncluded = false;
|
||||
|
||||
// create the polyline with the number of points adapted to the X range of the sub-curve
|
||||
for (unsigned int i=0; i < k; i++) {
|
||||
if (sc_isLinear[i]) {
|
||||
j++; // skip the first point
|
||||
poly_x.push_back(sc_x[j]);
|
||||
poly_y.push_back(sc_y[j++]);
|
||||
}
|
||||
else {
|
||||
for (unsigned int i=0; i < k; i++) {
|
||||
if (sc_isLinear[i]) {
|
||||
j++; // skip the first point
|
||||
poly_x.push_back(sc_x[j]);
|
||||
poly_y.push_back(sc_y[j++]);
|
||||
}
|
||||
else {
|
||||
nbr_points = (int)(((double)(ppn) * sc_length[i] )/ total_length);
|
||||
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]);
|
||||
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);
|
||||
}
|
||||
// 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
|
||||
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
|
||||
curveType->addEntry(argv0+"/images/curveType-flatLinear.png", M("CURVEEDITOR_LINEAR")); // 0 Linear
|
||||
|
@@ -110,9 +110,10 @@ class FlatCurveEditor : public CurveEditor {
|
||||
protected:
|
||||
// reflects the buttonType active selection ; used as a pre-'selectionChange' reminder value
|
||||
std::vector<double> controlPointsCurveEd;
|
||||
bool periodic;
|
||||
|
||||
public:
|
||||
FlatCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup);
|
||||
FlatCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup, bool isPeriodic = true);
|
||||
std::vector<double> getCurve ();
|
||||
};
|
||||
|
||||
|
@@ -56,8 +56,10 @@ void CurveEditorGroup::hideCurrentCurve() {
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
case (CT_Diagonal):
|
||||
if (!diagonalSubGroup) {
|
||||
@@ -68,7 +70,7 @@ CurveEditor* CurveEditorGroup::addCurve(CurveType cType, Glib::ustring curveLabe
|
||||
if (!flatSubGroup) {
|
||||
flatSubGroup = new FlatCurveEditorSubGroup(this);
|
||||
}
|
||||
return (CurveEditor*)flatSubGroup->addCurve(curveLabel);
|
||||
return (CurveEditor*)flatSubGroup->addCurve(curveLabel, periodic);
|
||||
default:
|
||||
return (CurveEditor*)NULL;
|
||||
break;
|
||||
|
@@ -70,7 +70,7 @@ public:
|
||||
void setColorProvider (ColorProvider* p) { cp = p; }
|
||||
CurveEditor* getDisplayedCurve () { return displayedCurve; }
|
||||
//void on_realize ();
|
||||
CurveEditor* addCurve(CurveType cType, Glib::ustring curveLabel);
|
||||
CurveEditor* addCurve(CurveType cType, Glib::ustring curveLabel, bool periodic = true);
|
||||
|
||||
protected:
|
||||
//void curveTypeToggled ();
|
||||
|
@@ -72,8 +72,8 @@ FlatCurveEditorSubGroup::~FlatCurveEditorSubGroup() {
|
||||
/*
|
||||
* Add a new curve to the curves list
|
||||
*/
|
||||
FlatCurveEditor* FlatCurveEditorSubGroup::addCurve(Glib::ustring curveLabel) {
|
||||
FlatCurveEditor* newCE = new FlatCurveEditor(curveLabel, parent, this);
|
||||
FlatCurveEditor* FlatCurveEditorSubGroup::addCurve(Glib::ustring curveLabel, bool isPeriodic) {
|
||||
FlatCurveEditor* newCE = new FlatCurveEditor(curveLabel, parent, this, isPeriodic);
|
||||
|
||||
// Initialization of the new curve
|
||||
storeCurveValues(newCE, getCurveFromGUI(FCT_MinMaxCPoints));
|
||||
@@ -99,6 +99,7 @@ void FlatCurveEditorSubGroup::switchGUI() {
|
||||
|
||||
switch((FlatCurveType)(dCurve->curveType->getSelected())) {
|
||||
case (FCT_MinMaxCPoints):
|
||||
CPointsCurve->setPeriodicity(dCurve->periodic); // Setting Periodicity before setting points
|
||||
CPointsCurve->setPoints (dCurve->controlPointsCurveEd);
|
||||
parent->pack_start (*CPointsCurveBox);
|
||||
CPointsCurveBox->check_resize();
|
||||
@@ -196,7 +197,7 @@ void FlatCurveEditorSubGroup::restoreDisplayedHistogram() {
|
||||
//paramCurve->updateBackgroundHistogram (parent->displayedCurve->histogram);
|
||||
CPointsCurve->updateBackgroundHistogram (parent->displayedCurve->histogram);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void FlatCurveEditorSubGroup::storeCurveValues (CurveEditor* ce, const std::vector<double>& p) {
|
||||
|
@@ -40,7 +40,7 @@ public:
|
||||
FlatCurveEditorSubGroup(CurveEditorGroup* prt);
|
||||
~FlatCurveEditorSubGroup();
|
||||
|
||||
FlatCurveEditor* addCurve(Glib::ustring curveLabel = "");
|
||||
FlatCurveEditor* addCurve(Glib::ustring curveLabel = "", bool periodic = true);
|
||||
//virtual void updateBackgroundHistogram (CurveEditor* ce);
|
||||
virtual void setColorProvider (ColorProvider* p);
|
||||
|
||||
|
@@ -31,6 +31,7 @@ MyCurve::MyCurve () : listener(NULL) {
|
||||
snapTo = ST_None;
|
||||
colorProvider = NULL;
|
||||
sized = RS_Pending;
|
||||
snapToElmt = -100;
|
||||
|
||||
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);
|
||||
@@ -54,3 +55,16 @@ void MyCurve::notifyListener () {
|
||||
if (listener)
|
||||
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> lpoint;
|
||||
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;
|
||||
enum ResizeState sized;
|
||||
|
||||
virtual std::vector<double> get_vector (int veclen) = 0;
|
||||
int getGraphMinSize() { return GRAPH_SIZE + RADIUS + 1; }
|
||||
bool snapCoordinate(double testedVal, double realVal);
|
||||
|
||||
public:
|
||||
MyCurve ();
|
||||
|
@@ -178,7 +178,10 @@ void MyDiagonalCurve::draw (int handle) {
|
||||
cr->stroke ();
|
||||
|
||||
// draw f(x)=x line
|
||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||
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());
|
||||
std::valarray<double> ds (1);
|
||||
ds[0] = 4;
|
||||
cr->set_dash (ds, 0);
|
||||
@@ -205,20 +208,30 @@ void MyDiagonalCurve::draw (int handle) {
|
||||
|
||||
// draw the cage of the NURBS curve
|
||||
if (curve.type==DCT_NURBS) {
|
||||
unsigned int nbPoints;
|
||||
std::valarray<double> ch_ds (1);
|
||||
ch_ds[0] = 2;
|
||||
cr->set_dash (ch_ds, 0);
|
||||
cr->set_source_rgb (0.0, 0.0, 0.0);
|
||||
std::vector<double> points = getPoints();
|
||||
for (int i = 1; i < (int)points.size(); ) {
|
||||
double x = ((innerWidth-1) * points[i++] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, innerWidth);
|
||||
double y = innerHeight - ((innerHeight-1) * points[i++] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, innerHeight);
|
||||
if (i==3)
|
||||
cr->move_to (x, y);
|
||||
nbPoints = ((int)points.size()-1)/2;
|
||||
for (unsigned int i = 1; i < nbPoints; i++) {
|
||||
int pos = i*2+1;
|
||||
|
||||
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
|
||||
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 ();
|
||||
}
|
||||
|
||||
@@ -232,7 +245,17 @@ void MyDiagonalCurve::draw (int handle) {
|
||||
// draw bullets
|
||||
if (curve.type!=DCT_Parametric)
|
||||
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 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;
|
||||
|
||||
case Gdk::BUTTON_PRESS:
|
||||
snapToElmt = -100;
|
||||
if (curve.type!=DCT_Parametric) {
|
||||
if (event->button.button == 1) {
|
||||
buttonPressed = true;
|
||||
@@ -338,6 +362,7 @@ bool MyDiagonalCurve::handleEvents (GdkEvent* event) {
|
||||
break;
|
||||
|
||||
case Gdk::BUTTON_RELEASE:
|
||||
snapToElmt = -100;
|
||||
if (curve.type!=DCT_Parametric) {
|
||||
if (buttonPressed && event->button.button == 1) {
|
||||
buttonPressed = false;
|
||||
@@ -398,7 +423,13 @@ bool MyDiagonalCurve::handleEvents (GdkEvent* event) {
|
||||
break;
|
||||
|
||||
case Gdk::MOTION_NOTIFY:
|
||||
snapToElmt = -100;
|
||||
if (curve.type == DCT_Linear || curve.type == DCT_Spline || curve.type == DCT_NURBS) {
|
||||
|
||||
snapToMinDist = 10.;
|
||||
snapToVal = 0.;
|
||||
snapToElmt = -100;
|
||||
|
||||
// get the pointer position
|
||||
getCursorPosition(event);
|
||||
|
||||
@@ -439,6 +470,9 @@ bool MyDiagonalCurve::handleEvents (GdkEvent* event) {
|
||||
ugpX += deltaX;
|
||||
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
|
||||
if (ugpX >= rightDeletionBound && (grab_point > 0 && grab_point < (num-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) {
|
||||
curve.x[grab_point] = -1.;
|
||||
}
|
||||
else
|
||||
// nextPosY is in the bounds
|
||||
curve.y[grab_point] = CLAMP(ugpY, 0.0, 1.0);
|
||||
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
|
||||
curve.y[grab_point] = CLAMP(ugpY, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
if (curve.x[grab_point] != prevPosX || curve.y[grab_point] != prevPosY) {
|
||||
// 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;
|
||||
|
||||
// the increment get smaller if modifier key are used, and "snap to" may be enabled
|
||||
if (control_key && shift_key) { snapTo = ST_Neighbors; }
|
||||
else if (control_key) { snapTo = ST_Identity; }
|
||||
else if (shift_key) { incrementX *= 0.04; incrementY *= 0.04; }
|
||||
if (control_key) { incrementX *= 0.05; incrementY *= 0.05; }
|
||||
if (shift_key) { snapTo = true; }
|
||||
|
||||
deltaX = (double)(cursorX - prevCursorX) * incrementX;
|
||||
deltaY = (double)(cursorY - prevCursorY) * incrementY;
|
||||
@@ -660,16 +723,16 @@ void MyDiagonalCurve::updateBackgroundHistogram (LUTu & hist) {
|
||||
|
||||
if (hist!=NULL) {
|
||||
//memcpy (bghist, hist, 256*sizeof(unsigned int));
|
||||
for (int i=0; i<256; i++) bghist[i]=hist[i];
|
||||
//hist = bghist;
|
||||
for (int i=0; i<256; i++) bghist[i]=hist[i];
|
||||
//hist = bghist;
|
||||
bghistvalid = true;
|
||||
}
|
||||
else
|
||||
bghistvalid = false;
|
||||
|
||||
|
||||
mcih->pending++;
|
||||
g_idle_add (diagonalmchistupdate, mcih);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MyDiagonalCurve::reset() {
|
||||
|
@@ -54,7 +54,7 @@ std::vector<double> MyFlatCurve::get_vector (int veclen) {
|
||||
|
||||
// Get the curve control points
|
||||
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
|
||||
std::vector<double> samples;
|
||||
@@ -157,13 +157,20 @@ void MyFlatCurve::draw () {
|
||||
double y0 = (double)RADIUS-0.5;
|
||||
double y1 = (double)RADIUS-0.5 + (double)innerHeight + 2.;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
double currX = (double)RADIUS-0.5 + (double)i*((double)innerWidth + 2.)/4.;
|
||||
double currY = (double)RADIUS-0.5 + (double)i*((double)innerHeight + 2.)/4.;
|
||||
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 currY = (double)RADIUS-0.5 + (double)i*((double)innerHeight + 2.)/4.;
|
||||
cr->move_to (x0, currY);
|
||||
cr->line_to (x1, currY);
|
||||
cr->move_to (currX, y0);
|
||||
cr->line_to (currX, y1);
|
||||
}
|
||||
}*/
|
||||
cr->stroke ();
|
||||
|
||||
// draw f(x)=0.5 line
|
||||
@@ -171,13 +178,14 @@ void MyFlatCurve::draw () {
|
||||
std::valarray<double> ds (1);
|
||||
ds[0] = 4;
|
||||
cr->set_dash (ds, 0);
|
||||
cr->move_to ((double)RADIUS+0.5 , (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->move_to (x0, (double)RADIUS+0.5 + (double)innerHeight/2.);
|
||||
cr->line_to (x1, (double)RADIUS+0.5 + (double)innerHeight/2.);
|
||||
cr->stroke ();
|
||||
|
||||
cr->unset_dash ();
|
||||
|
||||
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
||||
|
||||
cr->unset_dash ();
|
||||
cr->set_line_width (1.0);
|
||||
|
||||
// draw the color feedback of the control points
|
||||
@@ -347,6 +355,9 @@ void MyFlatCurve::draw () {
|
||||
else
|
||||
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)
|
||||
cr->set_source_rgb (0.0, 0.5, 0.0);
|
||||
else
|
||||
@@ -473,6 +484,7 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) {
|
||||
int src, dst;
|
||||
std::vector<double>::iterator itx, ity, itlt, itrt;
|
||||
|
||||
snapToElmt = -100;
|
||||
bool retval = false;
|
||||
int num = (int)curve.x.size();
|
||||
|
||||
@@ -548,7 +560,7 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) {
|
||||
curve.rightTangent.insert (itrt, 0);
|
||||
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.y[closest_point] = clampedY;
|
||||
curve.leftTangent[closest_point] = 0.35;
|
||||
@@ -695,14 +707,13 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) {
|
||||
case Gdk::MOTION_NOTIFY:
|
||||
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;
|
||||
enum MouseOverAreas prevArea = area;
|
||||
|
||||
snapToMinDist = 10.;
|
||||
snapToVal = 0.;
|
||||
snapToElmt = -100;
|
||||
|
||||
// get the pointer position
|
||||
getCursorPosition(event);
|
||||
getMouseOverArea();
|
||||
@@ -826,13 +837,22 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) {
|
||||
break;
|
||||
|
||||
case (FCT_EditedHandle_LeftTan): {
|
||||
double prevValue = ugpX;
|
||||
double prevValue = curve.leftTangent[lit_point];
|
||||
|
||||
ugpX -= deltaX*3;
|
||||
ugpX = CLAMP(ugpX, 0., 1.);
|
||||
curve.leftTangent[lit_point] = ugpX;
|
||||
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;
|
||||
}
|
||||
|
||||
if (ugpX != prevValue) {
|
||||
if (curve.leftTangent[lit_point] != prevValue) {
|
||||
interpolate ();
|
||||
draw ();
|
||||
notifyListener ();
|
||||
@@ -841,13 +861,22 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) {
|
||||
}
|
||||
|
||||
case (FCT_EditedHandle_RightTan): {
|
||||
double prevValue = ugpX;
|
||||
double prevValue = curve.rightTangent[lit_point];
|
||||
|
||||
ugpX += deltaX*3;
|
||||
ugpX = CLAMP(ugpX, 0., 1.);
|
||||
curve.rightTangent[lit_point] = ugpX;
|
||||
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;
|
||||
}
|
||||
|
||||
if (ugpX != prevValue) {
|
||||
if (curve.rightTangent[lit_point] != prevValue) {
|
||||
interpolate ();
|
||||
draw ();
|
||||
notifyListener ();
|
||||
@@ -855,7 +884,7 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) {
|
||||
break;
|
||||
}
|
||||
|
||||
// already process before the "switch" instruction
|
||||
// already processed before the "switch" instruction
|
||||
//case (FCT_EditedHandle_CPointUD):
|
||||
|
||||
default:
|
||||
@@ -995,9 +1024,41 @@ void MyFlatCurve::movePoint(bool moveX, bool moveY) {
|
||||
}
|
||||
|
||||
if (moveY) {
|
||||
|
||||
// we memorize the previous position of the point, for optimization purpose
|
||||
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
|
||||
if (ugpY >= topDeletionBound && nbPoints>2) {
|
||||
if (curve.x[lit_point] != -1.) {
|
||||
@@ -1015,7 +1076,7 @@ void MyFlatCurve::movePoint(bool moveX, bool moveY) {
|
||||
}
|
||||
else {
|
||||
// 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.) {
|
||||
// bring back the X value of the point if it reappear
|
||||
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) {
|
||||
// we recalculate the curve only if we have to
|
||||
// we recompute the curve only if we have to
|
||||
interpolate ();
|
||||
draw ();
|
||||
notifyListener ();
|
||||
@@ -1071,7 +1132,7 @@ void MyFlatCurve::getCursorPosition(GdkEvent* event) {
|
||||
preciseCursorX = cursorX * incrementX;
|
||||
preciseCursorY = cursorY * incrementY;
|
||||
|
||||
snapTo = ST_None;
|
||||
snapTo = false;
|
||||
|
||||
// update deltaX/Y if the user drags a point
|
||||
if (editedHandle != FCT_EditedHandle_None) {
|
||||
@@ -1080,9 +1141,8 @@ void MyFlatCurve::getCursorPosition(GdkEvent* event) {
|
||||
int shift_key = mod_type & GDK_SHIFT_MASK;
|
||||
|
||||
// the increment get smaller if modifier key are used, and "snap to" may be enabled
|
||||
if (control_key && shift_key) { snapTo = ST_Neighbors; }
|
||||
else if (control_key) { snapTo = ST_Identity; }
|
||||
else if (shift_key) { incrementX *= 0.04; incrementY *= 0.04; }
|
||||
if (control_key) { incrementX *= 0.05; incrementY *= 0.05; }
|
||||
if (shift_key) { snapTo = true; }
|
||||
|
||||
deltaX = (double)(cursorX - prevCursorX) * incrementX;
|
||||
deltaY = (double)(cursorY - prevCursorY) * incrementY;
|
||||
|
@@ -93,7 +93,7 @@ class MyFlatCurve : public MyCurve {
|
||||
double minDistanceX; // X minimal distance before point suppression
|
||||
double minDistanceY; // Y minimal distance before point suppression
|
||||
double deletedPointX; // Backup of the X value of the edited point, when deleted while being dragged
|
||||
HandlePosition leftTanHandle; // XY coordinate if the upper left and bottom right corner of the left tangent handle
|
||||
HandlePosition leftTanHandle; // XY coordinate if the upper left and bottom right corner of the left tangent handle
|
||||
HandlePosition rightTanHandle; // XY coordinate if the upper left and bottom right corner of the right tangent handle
|
||||
bool tanHandlesDisplayed; // True if the tangent handles are displayed
|
||||
bool periodic; // Flat curves are periodic by default
|
||||
@@ -114,6 +114,7 @@ class MyFlatCurve : public MyCurve {
|
||||
MyFlatCurve ();
|
||||
//~MyFlatCurve ();
|
||||
std::vector<double> getPoints ();
|
||||
void setPeriodicity (bool isPeriodic) { periodic = isPeriodic; };
|
||||
void setPoints (const std::vector<double>& p);
|
||||
void setType (FlatCurveType t);
|
||||
bool handleEvents (GdkEvent* event);
|
||||
|
Reference in New Issue
Block a user