Isis 3 Programmer Reference
BinaryStretchType.cpp
1#include "BinaryStretchType.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,
26 const QString &name, const QColor &color)
27 : StretchType(hist, stretch, name, color) {
28 p_startSlider = NULL;
29 p_startEdit = NULL;
30 p_endSlider = NULL;
31 p_endEdit = NULL;
32 p_sliderOverride = false;
33 p_editOverride = false;
34
35 QWidget *sliderWidget = new QWidget();
36 QGridLayout *sliderLayout = new QGridLayout();
37 sliderLayout->setColumnStretch(1, 10);
38
39 QLabel *startLabel = new QLabel("Start");
40 p_startSlider = new QSlider(Qt::Horizontal);
41 p_startSlider->setTickPosition(QSlider::NoTicks);
42 p_startSlider->setMinimum(0);
43 p_startSlider->setMaximum(1000);
44 p_startSlider->setPageStep(50);
45 connect(p_startSlider, SIGNAL(valueChanged(int)),
46 this, SLOT(startSliderMoved(int)));
47 p_startEdit = new QLineEdit();
48 p_startEdit->setMaximumWidth(75);
49 p_startEdit->setText(QString::number(p_cubeHist->Percent(25)));
50 connect(p_startEdit, SIGNAL(textChanged(const QString &)),
51 this, SLOT(startEditChanged(const QString &)));
52 sliderLayout->addWidget(startLabel, 0, 0);
53 sliderLayout->addWidget(p_startSlider, 0, 1);
54 sliderLayout->addWidget(p_startEdit, 0, 2);
55
56 QLabel *endLabel = new QLabel("End");
57 p_endSlider = new QSlider(Qt::Horizontal);
58 p_endSlider->setTickPosition(QSlider::NoTicks);
59 p_endSlider->setMinimum(0);
60 p_endSlider->setMaximum(1000);
61 p_endSlider->setValue(1000);
62 p_endSlider->setPageStep(50);
63 connect(p_endSlider, SIGNAL(valueChanged(int)),
64 this, SLOT(endSliderMoved(int)));
65 p_endEdit = new QLineEdit();
66 p_endEdit->setMaximumWidth(75);
67 p_endEdit->setText(QString::number(p_cubeHist->Percent(75)));
68 connect(p_endEdit, SIGNAL(textChanged(const QString &)),
69 this, SLOT(endEditChanged(const QString &)));
70 sliderLayout->addWidget(endLabel, 1, 0);
71 sliderLayout->addWidget(p_endSlider, 1, 1);
72 sliderLayout->addWidget(p_endEdit, 1, 2);
73
74 sliderWidget->setLayout(sliderLayout);
75 p_mainLayout->addWidget(sliderWidget, 1, 0);
76
77 setLayout(p_mainLayout);
79 }
80
81
87
88
101 double epsilon = p_cubeHist->BinSize();
102
103 Stretch interpretted;
104
105 double switch1 = 0.0;
106 double switch2 = 1.0;
107
108 if(newStretch.Pairs() == 2) {
109 // given a flat line?
110 if(newStretch.Output(0) == newStretch.Output(1)) {
111 // assume its binary all white
112 interpretted.AddPair(p_cubeHist->Minimum(), 255);
113 interpretted.AddPair(p_cubeHist->Maximum(), 255);
114 }
115 else {
116 // probably linear, figure out something reasonable
117 interpretted.AddPair(p_cubeHist->Minimum(), 0);
118
119 switch1 = newStretch.Input(0);
120 if(switch1 < p_cubeHist->Minimum())
121 switch1 = p_cubeHist->Minimum() + epsilon;
122
123 interpretted.AddPair(switch1, 0);
124 interpretted.AddPair(switch1 + epsilon, 255);
125
126 switch2 = newStretch.Input(1);
127 if(switch2 <= switch1 + epsilon)
128 switch2 = switch1 + epsilon + epsilon;
129
130 interpretted.AddPair(switch2, 255);
131 interpretted.AddPair(switch2 + epsilon, 0);
132
133 double end = p_cubeHist->Maximum();
134 if(end <= switch2 + epsilon)
135 end = switch2 + epsilon + epsilon;
136
137 interpretted.AddPair(end, 0);
138 }
139 }
140 else if(newStretch.Pairs() == 4) {
141 if(newStretch.Output(0) > 127) {
142 interpretted.AddPair(p_cubeHist->Minimum(), 255);
143
144 switch1 = newStretch.Input(1);
145 if(switch1 <= p_cubeHist->Minimum())
146 switch1 = p_cubeHist->Minimum() + epsilon;
147
148 interpretted.AddPair(switch1, 255);
149 interpretted.AddPair(switch1 + epsilon, 0);
150
151 double end = p_cubeHist->Maximum();
152 if(end <= switch1 + epsilon)
153 end = switch1 + epsilon + epsilon;
154
155 switch2 = end;
156
157 interpretted.AddPair(end, 0);
158 }
159 else {
160 interpretted.AddPair(p_cubeHist->Minimum(), 0);
161
162 switch1 = newStretch.Input(1);
163 if(switch1 < p_cubeHist->Minimum())
164 switch1 = p_cubeHist->Minimum() + epsilon;
165
166 interpretted.AddPair(switch1, 0);
167 interpretted.AddPair(switch1 + epsilon, 255);
168
169 double end = p_cubeHist->Maximum();
170 if(end <= switch1 + epsilon)
171 end = switch1 + epsilon + epsilon;
172 switch2 = end;
173
174 interpretted.AddPair(end, 255);
175 }
176 }
177 // 6 pairs means the 255 values are in the middle (typical)
178 else if(newStretch.Pairs() == 6) {
179 interpretted.AddPair(p_cubeHist->Minimum(), 0);
180
181 switch1 = newStretch.Input(1);
182 if(switch1 <= p_cubeHist->Minimum())
183 switch1 = p_cubeHist->Minimum() + epsilon;
184
185 interpretted.AddPair(switch1, 0);
186 interpretted.AddPair(switch1 + epsilon, 255);
187
188
189 switch2 = newStretch.Input(3);
190 if(switch2 <= switch1 + epsilon)
191 switch2 = switch1 + epsilon + epsilon;
192
193 interpretted.AddPair(switch2, 255);
194 interpretted.AddPair(switch2 + epsilon, 0);
195
196 double end = p_cubeHist->Maximum();
197 if(end <= switch2 + epsilon)
198 end = switch2 + epsilon + epsilon;
199
200 interpretted.AddPair(end, 0);
201 }
202
203 if(!interpretted.Pairs()) {
204 interpretted.CopyPairs(calculateNewStretch());
205 switch1 = p_startEdit->text().toDouble();
206 switch2 = p_endEdit->text().toDouble();
207 }
208
209 bool changed = (interpretted.Text() != p_stretch->Text());
210
211 p_editOverride = true;
212 if(changed) {
213 p_stretch->CopyPairs(interpretted);
214 p_startEdit->setText(QString::number(switch1));
215 p_endEdit->setText(QString::number(switch2));
216 }
217
218 // regardless of it all, slider positions could need changed...
219 startEditChanged(QString());
220 endEditChanged(QString());
221 p_editOverride = false;
222
223 if(changed) {
224 emit stretchChanged();
225 }
226 }
227
228
235 return;
236
237 if(p_startSlider->value() >= p_endSlider->value()) {
238 p_startSlider->setValue(p_endSlider->value() - 1);
239 return;
240 }
241
242 double value = p_cubeHist->Minimum();
243 value += p_startSlider->value() *
244 (p_cubeHist->Maximum() - p_cubeHist->Minimum()) / 1000.0;
245 p_startEdit->setText(QString::number(value));
246 }
247
248
254 double value = p_startEdit->text().toDouble();
255
256 if(value >= p_endEdit->text().toDouble()) {
257 return;
258 }
259
260 double percentage = value - p_cubeHist->Minimum();
261 percentage /= (p_cubeHist->Maximum() - p_cubeHist->Minimum());
262 int valuePos = (int)(percentage * 1000.0);
263
264 p_sliderOverride = true;
265 p_startSlider->setValue(valuePos);
266 p_sliderOverride = false;
267
268 if(p_editOverride) return;
269
270 Stretch newStretch = calculateNewStretch();
271
272 if(newStretch.Text() != p_stretch->Text()) {
273 p_stretch->CopyPairs(newStretch);
274 emit stretchChanged();
275 }
276 }
277
278
285 return;
286
287 if(p_endSlider->value() <= p_startSlider->value()) {
288 p_endSlider->setValue(p_startSlider->value() + 1);
289 return;
290 }
291
292 double value = p_cubeHist->Minimum();
293 value += p_endSlider->value() *
294 (p_cubeHist->Maximum() - p_cubeHist->Minimum()) / 1000.0;
295 p_endEdit->setText(QString::number(value));
296 }
297
298
303 void BinaryStretchType::endEditChanged(const QString &) {
304 double value = p_endEdit->text().toDouble();
305
306 if(value <= p_startEdit->text().toDouble()) {
307 return;
308 }
309
310 double percentage = value - p_cubeHist->Minimum();
311 percentage /= (p_cubeHist->Maximum() - p_cubeHist->Minimum());
312 int valuePos = (int)(percentage * 1000.0);
313
314 p_sliderOverride = true;
315 p_endSlider->setValue(valuePos);
316 p_sliderOverride = false;
317
318 if(p_editOverride) return;
319
320 Stretch newStretch = calculateNewStretch();
321
322 if(newStretch.Text() != p_stretch->Text()) {
323 p_stretch->CopyPairs(newStretch);;
324 emit stretchChanged();
325 }
326 }
327
328
336 double epsilon = p_cubeHist->BinSize();
337
338 if(epsilon == 0) {
339 epsilon = (p_cubeHist->Maximum() - p_cubeHist->Minimum()) / 65536;
340 }
341
342 Stretch newStretch;
343
344 if(epsilon == 0) {
345 return newStretch;
346 }
347 // Start high?
348 double startPt = p_startEdit->text().toDouble();
349 if(fabs(startPt - p_cubeHist->Minimum()) < epsilon ||
350 startPt <= p_cubeHist->Minimum()) {
351 newStretch.AddPair(p_cubeHist->Minimum(), 255);
352 startPt = p_cubeHist->Minimum() - epsilon;
353 }
354 else {
355 newStretch.AddPair(p_cubeHist->Minimum(), 0);
356 newStretch.AddPair(startPt, 0);
357 newStretch.AddPair(startPt + epsilon, 255);
358 }
359
360 // End high?
361 double endPt = p_endEdit->text().toDouble();
362 if(endPt <= startPt + epsilon) {
363 endPt = startPt + 2 * epsilon;
364 }
365
366 if(fabs(endPt + epsilon - p_cubeHist->Maximum()) < epsilon ||
367 endPt + epsilon >= p_cubeHist->Maximum()) {
368 newStretch.AddPair(p_cubeHist->Maximum(), 255);
369 }
370 else {
371 newStretch.AddPair(endPt, 255);
372 newStretch.AddPair(endPt + epsilon, 0);
373 newStretch.AddPair(p_cubeHist->Maximum(), 0);
374 }
375
376 return newStretch;
377 }
378
379
386 CubeStretch cubeStretch(*p_stretch, "Binary");
387 return cubeStretch;
388 }
389}
BinaryStretchType(const Histogram &, const Stretch &, const QString &name, const QColor &color)
This constructs a binary stretch type.
virtual CubeStretch getStretch()
Gets the CubeStretch for this Binary Stretch.
QSlider * p_endSlider
End point slider.
bool p_sliderOverride
This is used to let the edits be changed to where sliders cant go.
void startEditChanged(const QString &)
A new start point was typed in.
void startSliderMoved(int)
This is called when the start point slider moves.
QLineEdit * p_endEdit
End point edit.
virtual void setStretch(Stretch)
Given an arbitrary stretch, this will re-interpret it, as best as possible, into a binary stretch.
void endSliderMoved(int)
This is called when the end point slider moves.
~BinaryStretchType()
Destroys the binary stretch.
Stretch calculateNewStretch()
This uses the GUI elements to calculate the current binary stretch.
void endEditChanged(const QString &)
A new end point was typed in.
QSlider * p_startSlider
Start point slider.
bool p_editOverride
This is used to let the edits be changed without updating the stretch.
QLineEdit * p_startEdit
Start point edit.
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 Percent(const double percent) const
Computes and returns the value at X percent of the histogram.
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