Isis 3 Programmer Reference
SawtoothStretchType.cpp
1#include "SawtoothStretchType.h"
2
3#include <QVBoxLayout>
4#include <QLayout>
5#include <QLineEdit>
6#include <QLabel>
7#include <QTableWidget>
8
9#include "CubeViewport.h"
10#include "HistogramWidget.h"
11#include "Statistics.h"
12#include "Stretch.h"
13#include "CubeStretch.h"
14
15namespace Isis {
25 const Stretch &stretch, const QString &name, const QColor &color) :
26 StretchType(hist, stretch, name, color) {
27 p_offsetSlider = NULL;
28 p_widthSlider = NULL;
29 p_offsetEdit = NULL;
30 p_widthEdit = NULL;
31 p_sliderOverride = false;
32
33 QWidget *sliderWidget = new QWidget();
34 QGridLayout *sliderLayout = new QGridLayout();
35 sliderLayout->setColumnStretch(1, 10);
36
37 QLabel *startLabel = new QLabel("Offset");
38 p_offsetSlider = new QSlider(Qt::Horizontal);
39 p_offsetSlider->setTickPosition(QSlider::NoTicks);
40 p_offsetSlider->setMinimum(0);
41 p_offsetSlider->setMaximum(1000);
42 p_offsetSlider->setPageStep(50);
43 connect(p_offsetSlider, SIGNAL(valueChanged(int)),
44 this, SLOT(offsetSliderMoved(int)));
45 p_offsetEdit = new QLineEdit();
46 p_offsetEdit->setMaximumWidth(75);
47 p_offsetEdit->setText(QString::number(
49 ));
50 connect(p_offsetEdit, SIGNAL(textChanged(const QString &)),
51 this, SLOT(offsetEditChanged(const QString &)));
52 sliderLayout->addWidget(startLabel, 0, 0);
53 sliderLayout->addWidget(p_offsetSlider, 0, 1);
54 sliderLayout->addWidget(p_offsetEdit, 0, 2);
55
56 QLabel *widthLabel = new QLabel("Width");
57 p_widthSlider = new QSlider(Qt::Horizontal);
58 p_widthSlider->setTickPosition(QSlider::NoTicks);
59 p_widthSlider->setMinimum(0);
60 p_widthSlider->setMaximum(1000);
61 p_widthSlider->setPageStep(50);
62 connect(p_widthSlider, SIGNAL(valueChanged(int)),
63 this, SLOT(widthSliderMoved(int)));
64 p_widthEdit = new QLineEdit();
65 p_widthEdit->setMaximumWidth(75);
66 connect(p_widthEdit, SIGNAL(textChanged(const QString &)),
67 this, SLOT(widthEditChanged(const QString &)));
68 sliderLayout->addWidget(widthLabel, 1, 0);
69 sliderLayout->addWidget(p_widthSlider, 1, 1);
70 sliderLayout->addWidget(p_widthEdit, 1, 2);
71
72 sliderWidget->setLayout(sliderLayout);
73 p_mainLayout->addWidget(sliderWidget, 1, 0);
74
75 setLayout(p_mainLayout);
76
77 p_widthEdit->setText(QString::number(
79 ));
81 }
82
83
89
90
105 Stretch interpretted;
106 double offset = 0.0;
107 double width = 0.0;
108 bool changed = false;
109
110 // Too few pairs to do a saw tooth with
111 if(newStretch.Pairs() < 3) {
112 return;
113 }
114 else {
115 // find an offset... should be the second or third point
116 offset = newStretch.Input(1);
117
118 // offset should always be a low point
119 if(newStretch.Output(1) > 127)
120 offset = newStretch.Input(2);
121
122 width = (newStretch.Input(2) - newStretch.Input(0)) / 2;
123
124 interpretted.CopyPairs(calculateNewStretch(offset, width));
125
126 double deltaOffset = fabs(p_offsetEdit->text().toDouble() - offset);
127 changed = (changed || (deltaOffset > p_cubeHist->BinSize()));
128
129 double deltaWidth = fabs(p_widthEdit->text().toDouble() - width);
130 changed = (changed || (deltaWidth > p_cubeHist->BinSize()));
131 }
132
133 if(changed) {
134 p_stretch->CopyPairs(interpretted);
135 p_offsetEdit->setText(QString::number(offset));
136 p_widthEdit->setText(QString::number(width));
137 }
138
139 // regardless of it all, slider positions could need changed...
140 offsetEditChanged(QString());
141 widthEditChanged(QString());
142
143 if(changed) {
144 emit stretchChanged();
145 }
146 }
147
148
154 if(p_offsetSlider->value() >= p_widthSlider->value())
155 p_offsetSlider->setValue(p_widthSlider->value() - 1);
156
158 return;
159
160 double value = p_cubeHist->Minimum();
161 value += p_offsetSlider->value() * 2 *
162 (p_cubeHist->Maximum() - p_cubeHist->Minimum()) / 1000.0;
163 p_offsetEdit->setText(QString::number(value));
164 }
165
166
173 double value = p_offsetEdit->text().toDouble();
174
175 double percentage = value - p_cubeHist->Minimum();
176 percentage /= (p_cubeHist->Maximum() - p_cubeHist->Minimum()) * 2;
177 int valuePos = (int)(percentage * 1000.0);
178
179 p_sliderOverride = true;
180 p_offsetSlider->setValue(valuePos);
181 p_sliderOverride = false;
182
183 Stretch newStretch = calculateNewStretch();
184
185 if(newStretch.Text() != p_stretch->Text()) {
186 p_stretch->CopyPairs(newStretch);
187 emit stretchChanged();
188 }
189
190 }
191
192
198 if(p_widthSlider->value() <= p_offsetSlider->value())
199 p_widthSlider->setValue(p_offsetSlider->value() + 1);
200
202 return;
203
204 double highVal = p_cubeHist->Maximum() - p_cubeHist->Minimum();
205 double lowVal = p_cubeHist->BinSize();
206 double value = lowVal + p_widthSlider->value() *
207 (highVal - lowVal) / 1000.0;
208 p_widthEdit->setText(QString::number(value));
209 }
210
211
218 double value = p_widthEdit->text().toDouble();
219
220 double highVal = p_cubeHist->Maximum() - p_cubeHist->Minimum();
221 double lowVal = p_cubeHist->BinSize();
222
223 double percentage = value - lowVal;
224 percentage /= (highVal - lowVal);
225 int valuePos = (int)(percentage * 1000.0);
226
227 p_sliderOverride = true;
228 p_widthSlider->setValue(valuePos);
229 p_sliderOverride = false;
230
231 Stretch newStretch = calculateNewStretch();
232
233 if(newStretch.Text() != p_stretch->Text()) {
234 p_stretch->CopyPairs(newStretch);
235 emit stretchChanged();
236 }
237 }
238
239
252 double width) {
253 Stretch stretch;
254 width = fabs(width);
255
256 if(width < p_cubeHist->BinSize())
257 width = p_cubeHist->BinSize();
258
259 // Still can't do it? Give up
260 if(width <= 0) return Stretch();
261
262 bool high = false;
263
264 // We want leftPoint to be our starting point for the sawtooth, one left of
265 // the minimum
266 double leftPoint = offset;
267
268 // If leftPoint is too far left, move it right
269 while(leftPoint < p_cubeHist->Minimum() - width) {
270 leftPoint += width;
271 high = !high;
272 }
273
274 // If leftPoint is too far fight, move it left
275 while(leftPoint >= p_cubeHist->Minimum()) {
276 leftPoint -= width;
277 high = !high;
278 }
279
280 double currPoint = leftPoint;
281
282 bool terminated = false;
283 while(!terminated) {
284 int outValue = (high) ? 255 : 0;
285
286 // This conversion to a string & back prevents infinite loops due to
287 // rounding errors and disagreements betweeen double to string
288 // conversions later on (in setStretch)
289 stretch.AddPair(QString::number(currPoint).toDouble(), outValue);
290
291 if(currPoint > p_cubeHist->Maximum()) {
292 terminated = true;
293 }
294
295 high = !high;
296 currPoint += width;
297 }
298
299 return stretch;
300 }
301
302
309 return calculateNewStretch(p_offsetEdit->text().toDouble(),
310 p_widthEdit->text().toDouble());
311 }
312
313
320 CubeStretch cubeStretch(*p_stretch, "Sawtooth");
321 return cubeStretch;
322 }
323}
324
Stores stretch information for a cube.
Definition CubeStretch.h:27
Container of a cube histogram.
Definition Histogram.h:74
double BinSize() const
Returns the size of an individual bin.
double Median() const
Returns the median.
void widthSliderMoved(int)
This is called when the sawtooth width slider moves.
virtual void setStretch(Stretch)
Given an arbitrary stretch, this will re-interpret it, as best as possible, into a sawtooth stretch.
virtual CubeStretch getStretch()
Gets the CubeStretch for this Sawtooth Stretch.
QLineEdit * p_widthEdit
Width edit.
SawtoothStretchType(const Histogram &, const Stretch &, const QString &name, const QColor &color)
This initializes a sawtooth stretch type.
void offsetEditChanged(const QString &)
This is called when the the sawtooth offset edit changes.
void widthEditChanged(const QString &)
This is called when the the sawtooth width edit changes.
QLineEdit * p_offsetEdit
Offset edit.
Stretch calculateNewStretch()
This calculates a new stretch using the GUI edits.
void offsetSliderMoved(int)
This is called when the sawtooth offset slider moves.
bool p_sliderOverride
This is used to let the edits be changed to where sliders cant go.
QSlider * p_widthSlider
Width slider.
QSlider * p_offsetSlider
Offset slider.
double Minimum() const
Returns the absolute minimum double found in all data passed through the AddData method.
double Maximum() const
Returns the absolute maximum double found in all data passed through the AddData method.
Pixel value mapper.
Definition Stretch.h:58
void CopyPairs(const Stretch &other)
Copies the stretch pairs from another Stretch object, but maintains special pixel values.
Definition Stretch.cpp:392
void AddPair(const double input, const double output)
Adds a stretch pair to the list of pairs.
Definition Stretch.cpp:48
QString Text() const
Converts stretch pair to a string.
Definition Stretch.cpp:268
This is the base class for advanced stretches.
Definition StretchType.h:39
Stretch * p_stretch
Current stretch pairs stored here.
Definition StretchType.h:71
Histogram * p_cubeHist
Visible area histogram.
Definition StretchType.h:68
QGridLayout * p_mainLayout
Main layout.
Definition StretchType.h:67
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition IString.cpp:149