USGS

Isis 3.0 Object Programmers' Reference

Home

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 
14 namespace Isis {
24  const Stretch &stretch, const QString &name, const QColor &color) :
25  StretchType(hist, stretch, name, color) {
26  p_offsetSlider = NULL;
27  p_widthSlider = NULL;
28  p_offsetEdit = NULL;
29  p_widthEdit = NULL;
30  p_sliderOverride = false;
31 
32  QWidget *sliderWidget = new QWidget();
33  QGridLayout *sliderLayout = new QGridLayout();
34  sliderLayout->setColumnStretch(1, 10);
35 
36  QLabel *startLabel = new QLabel("Offset");
37  p_offsetSlider = new QSlider(Qt::Horizontal);
38  p_offsetSlider->setTickPosition(QSlider::NoTicks);
39  p_offsetSlider->setMinimum(0);
40  p_offsetSlider->setMaximum(1000);
41  p_offsetSlider->setPageStep(50);
42  connect(p_offsetSlider, SIGNAL(valueChanged(int)),
43  this, SLOT(offsetSliderMoved(int)));
44  p_offsetEdit = new QLineEdit();
45  p_offsetEdit->setMaximumWidth(75);
46  p_offsetEdit->setText(QString::number(
48  ));
49  connect(p_offsetEdit, SIGNAL(textChanged(const QString &)),
50  this, SLOT(offsetEditChanged(const QString &)));
51  sliderLayout->addWidget(startLabel, 0, 0);
52  sliderLayout->addWidget(p_offsetSlider, 0, 1);
53  sliderLayout->addWidget(p_offsetEdit, 0, 2);
54 
55  QLabel *widthLabel = new QLabel("Width");
56  p_widthSlider = new QSlider(Qt::Horizontal);
57  p_widthSlider->setTickPosition(QSlider::NoTicks);
58  p_widthSlider->setMinimum(0);
59  p_widthSlider->setMaximum(1000);
60  p_widthSlider->setPageStep(50);
61  connect(p_widthSlider, SIGNAL(valueChanged(int)),
62  this, SLOT(widthSliderMoved(int)));
63  p_widthEdit = new QLineEdit();
64  p_widthEdit->setMaximumWidth(75);
65  connect(p_widthEdit, SIGNAL(textChanged(const QString &)),
66  this, SLOT(widthEditChanged(const QString &)));
67  sliderLayout->addWidget(widthLabel, 1, 0);
68  sliderLayout->addWidget(p_widthSlider, 1, 1);
69  sliderLayout->addWidget(p_widthEdit, 1, 2);
70 
71  sliderWidget->setLayout(sliderLayout);
72  p_mainLayout->addWidget(sliderWidget, 1, 0);
73 
74  setLayout(p_mainLayout);
75 
76  p_widthEdit->setText(QString::number(
78  ));
80  }
81 
82 
87  }
88 
89 
103  void SawtoothStretchType::setStretch(const Stretch newStretch) {
104  Stretch interpretted;
105  double offset = 0.0;
106  double width = 0.0;
107  bool changed = false;
108 
109  if(newStretch.Pairs() < 3) {
110  // Disable all interpretation of linear stretches
111  interpretted.CopyPairs(calculateNewStretch());
112  offset = p_offsetEdit->text().toDouble();
113  width = p_widthEdit->text().toDouble();
114  changed = true;
115  }
116  else {
117  // find an offset... should be the second or third point
118  offset = newStretch.Input(1);
119 
120  // offset should always be a low point
121  if(newStretch.Output(1) > 127)
122  offset = newStretch.Input(2);
123 
124  width = (newStretch.Input(2) - newStretch.Input(0)) / 2;
125 
126  interpretted.CopyPairs(calculateNewStretch(offset, width));
127 
128  double deltaOffset = fabs(p_offsetEdit->text().toDouble() - offset);
129  changed = (changed || (deltaOffset > p_cubeHist->BinSize()));
130 
131  double deltaWidth = fabs(p_widthEdit->text().toDouble() - width);
132  changed = (changed || (deltaWidth > p_cubeHist->BinSize()));
133  }
134 
135  if(changed) {
136  p_stretch->CopyPairs(interpretted);
137  p_offsetEdit->setText(QString::number(offset));
138  p_widthEdit->setText(QString::number(width));
139  }
140 
141  // regardless of it all, slider positions could need changed...
142  offsetEditChanged(QString());
143  widthEditChanged(QString());
144 
145  if(changed) {
146  emit stretchChanged();
147  }
148  }
149 
150 
156  if(p_offsetSlider->value() >= p_widthSlider->value())
157  p_offsetSlider->setValue(p_widthSlider->value() - 1);
158 
159  if(p_sliderOverride)
160  return;
161 
162  double value = p_cubeHist->Minimum();
163  value += p_offsetSlider->value() * 2 *
164  (p_cubeHist->Maximum() - p_cubeHist->Minimum()) / 1000.0;
165  p_offsetEdit->setText(QString::number(value));
166  }
167 
168 
175  double value = p_offsetEdit->text().toDouble();
176 
177  double percentage = value - p_cubeHist->Minimum();
178  percentage /= (p_cubeHist->Maximum() - p_cubeHist->Minimum()) * 2;
179  int valuePos = (int)(percentage * 1000.0);
180 
181  p_sliderOverride = true;
182  p_offsetSlider->setValue(valuePos);
183  p_sliderOverride = false;
184 
185  Stretch newStretch = calculateNewStretch();
186 
187  if(newStretch.Text() != p_stretch->Text()) {
188  p_stretch->CopyPairs(newStretch);
189  emit stretchChanged();
190  }
191 
192  }
193 
194 
200  if(p_widthSlider->value() <= p_offsetSlider->value())
201  p_widthSlider->setValue(p_offsetSlider->value() + 1);
202 
203  if(p_sliderOverride)
204  return;
205 
206  double highVal = p_cubeHist->Maximum() - p_cubeHist->Minimum();
207  double lowVal = p_cubeHist->BinSize();
208  double value = lowVal + p_widthSlider->value() *
209  (highVal - lowVal) / 1000.0;
210  p_widthEdit->setText(QString::number(value));
211  }
212 
213 
220  double value = p_widthEdit->text().toDouble();
221 
222  double highVal = p_cubeHist->Maximum() - p_cubeHist->Minimum();
223  double lowVal = p_cubeHist->BinSize();
224 
225  double percentage = value - lowVal;
226  percentage /= (highVal - lowVal);
227  int valuePos = (int)(percentage * 1000.0);
228 
229  p_sliderOverride = true;
230  p_widthSlider->setValue(valuePos);
231  p_sliderOverride = false;
232 
233  Stretch newStretch = calculateNewStretch();
234 
235  if(newStretch.Text() != p_stretch->Text()) {
236  p_stretch->CopyPairs(newStretch);
237  emit stretchChanged();
238  }
239  }
240 
241 
254  double width) {
255  Stretch stretch;
256  width = fabs(width);
257 
258  if(width < p_cubeHist->BinSize())
259  width = p_cubeHist->BinSize();
260 
261  // Still can't do it? Give up
262  if(width <= 0) return Stretch();
263 
264  bool high = false;
265 
266  // We want leftPoint to be our starting point for the sawtooth, one left of
267  // the minimum
268  double leftPoint = offset;
269 
270  // If leftPoint is too far left, move it right
271  while(leftPoint < p_cubeHist->Minimum() - width) {
272  leftPoint += width;
273  high = !high;
274  }
275 
276  // If leftPoint is too far fight, move it left
277  while(leftPoint >= p_cubeHist->Minimum()) {
278  leftPoint -= width;
279  high = !high;
280  }
281 
282  double currPoint = leftPoint;
283 
284  bool terminated = false;
285  while(!terminated) {
286  int outValue = (high) ? 255 : 0;
287 
288  // This conversion to a string & back prevents infinite loops due to
289  // rounding errors and disagreements betweeen double to string
290  // conversions later on (in setStretch)
291  stretch.AddPair(QString::number(currPoint).toDouble(), outValue);
292 
293  if(currPoint > p_cubeHist->Maximum()) {
294  terminated = true;
295  }
296 
297  high = !high;
298  currPoint += width;
299  }
300 
301  return stretch;
302  }
303 
304 
311  return calculateNewStretch(p_offsetEdit->text().toDouble(),
312  p_widthEdit->text().toDouble());
313  }
314 }
315