|
Isis 3.0 Object Programmers' Reference |
Home |
00001 #include "SawtoothStretchType.h" 00002 00003 #include <QVBoxLayout> 00004 #include <QLayout> 00005 #include <QLineEdit> 00006 #include <QLabel> 00007 #include <QTableWidget> 00008 00009 #include "CubeViewport.h" 00010 #include "HistogramWidget.h" 00011 #include "Statistics.h" 00012 #include "Stretch.h" 00013 00014 namespace Isis { 00023 SawtoothStretchType::SawtoothStretchType(const Histogram &hist, 00024 const Stretch &stretch, const QString &name, const QColor &color) : 00025 StretchType(hist, stretch, name, color) { 00026 p_offsetSlider = NULL; 00027 p_widthSlider = NULL; 00028 p_offsetEdit = NULL; 00029 p_widthEdit = NULL; 00030 p_sliderOverride = false; 00031 00032 QWidget *sliderWidget = new QWidget(); 00033 QGridLayout *sliderLayout = new QGridLayout(); 00034 sliderLayout->setColumnStretch(1, 10); 00035 00036 QLabel *startLabel = new QLabel("Offset"); 00037 p_offsetSlider = new QSlider(Qt::Horizontal); 00038 p_offsetSlider->setTickPosition(QSlider::NoTicks); 00039 p_offsetSlider->setMinimum(0); 00040 p_offsetSlider->setMaximum(1000); 00041 p_offsetSlider->setPageStep(50); 00042 connect(p_offsetSlider, SIGNAL(valueChanged(int)), 00043 this, SLOT(offsetSliderMoved(int))); 00044 p_offsetEdit = new QLineEdit(); 00045 p_offsetEdit->setMaximumWidth(75); 00046 p_offsetEdit->setText(QString::number( 00047 p_cubeHist->Maximum() - p_cubeHist->Minimum() 00048 )); 00049 connect(p_offsetEdit, SIGNAL(textChanged(const QString &)), 00050 this, SLOT(offsetEditChanged(const QString &))); 00051 sliderLayout->addWidget(startLabel, 0, 0); 00052 sliderLayout->addWidget(p_offsetSlider, 0, 1); 00053 sliderLayout->addWidget(p_offsetEdit, 0, 2); 00054 00055 QLabel *widthLabel = new QLabel("Width"); 00056 p_widthSlider = new QSlider(Qt::Horizontal); 00057 p_widthSlider->setTickPosition(QSlider::NoTicks); 00058 p_widthSlider->setMinimum(0); 00059 p_widthSlider->setMaximum(1000); 00060 p_widthSlider->setPageStep(50); 00061 connect(p_widthSlider, SIGNAL(valueChanged(int)), 00062 this, SLOT(widthSliderMoved(int))); 00063 p_widthEdit = new QLineEdit(); 00064 p_widthEdit->setMaximumWidth(75); 00065 connect(p_widthEdit, SIGNAL(textChanged(const QString &)), 00066 this, SLOT(widthEditChanged(const QString &))); 00067 sliderLayout->addWidget(widthLabel, 1, 0); 00068 sliderLayout->addWidget(p_widthSlider, 1, 1); 00069 sliderLayout->addWidget(p_widthEdit, 1, 2); 00070 00071 sliderWidget->setLayout(sliderLayout); 00072 p_mainLayout->addWidget(sliderWidget, 1, 0); 00073 00074 setLayout(p_mainLayout); 00075 00076 p_widthEdit->setText(QString::number( 00077 p_cubeHist->Median() - p_cubeHist->Minimum() 00078 )); 00079 setStretch(calculateNewStretch()); 00080 } 00081 00082 00086 SawtoothStretchType::~SawtoothStretchType() { 00087 } 00088 00089 00103 void SawtoothStretchType::setStretch(const Stretch newStretch) { 00104 Stretch interpretted; 00105 double offset = 0.0; 00106 double width = 0.0; 00107 bool changed = false; 00108 00109 if(newStretch.Pairs() < 3) { 00110 // Disable all interpretation of linear stretches 00111 interpretted.CopyPairs(calculateNewStretch()); 00112 offset = p_offsetEdit->text().toDouble(); 00113 width = p_widthEdit->text().toDouble(); 00114 changed = true; 00115 } 00116 else { 00117 // find an offset... should be the second or third point 00118 offset = newStretch.Input(1); 00119 00120 // offset should always be a low point 00121 if(newStretch.Output(1) > 127) 00122 offset = newStretch.Input(2); 00123 00124 width = (newStretch.Input(2) - newStretch.Input(0)) / 2; 00125 00126 interpretted.CopyPairs(calculateNewStretch(offset, width)); 00127 00128 double deltaOffset = fabs(p_offsetEdit->text().toDouble() - offset); 00129 changed = (changed || (deltaOffset > p_cubeHist->BinSize())); 00130 00131 double deltaWidth = fabs(p_widthEdit->text().toDouble() - width); 00132 changed = (changed || (deltaWidth > p_cubeHist->BinSize())); 00133 } 00134 00135 if(changed) { 00136 p_stretch->CopyPairs(interpretted); 00137 p_offsetEdit->setText(QString::number(offset)); 00138 p_widthEdit->setText(QString::number(width)); 00139 } 00140 00141 // regardless of it all, slider positions could need changed... 00142 offsetEditChanged(QString()); 00143 widthEditChanged(QString()); 00144 00145 if(changed) { 00146 emit stretchChanged(); 00147 } 00148 } 00149 00150 00155 void SawtoothStretchType::offsetSliderMoved(int) { 00156 if(p_offsetSlider->value() >= p_widthSlider->value()) 00157 p_offsetSlider->setValue(p_widthSlider->value() - 1); 00158 00159 if(p_sliderOverride) 00160 return; 00161 00162 double value = p_cubeHist->Minimum(); 00163 value += p_offsetSlider->value() * 2 * 00164 (p_cubeHist->Maximum() - p_cubeHist->Minimum()) / 1000.0; 00165 p_offsetEdit->setText(QString::number(value)); 00166 } 00167 00168 00174 void SawtoothStretchType::offsetEditChanged(const QString &) { 00175 double value = p_offsetEdit->text().toDouble(); 00176 00177 double percentage = value - p_cubeHist->Minimum(); 00178 percentage /= (p_cubeHist->Maximum() - p_cubeHist->Minimum()) * 2; 00179 int valuePos = (int)(percentage * 1000.0); 00180 00181 p_sliderOverride = true; 00182 p_offsetSlider->setValue(valuePos); 00183 p_sliderOverride = false; 00184 00185 Stretch newStretch = calculateNewStretch(); 00186 00187 if(newStretch.Text() != p_stretch->Text()) { 00188 p_stretch->CopyPairs(newStretch); 00189 emit stretchChanged(); 00190 } 00191 00192 } 00193 00194 00199 void SawtoothStretchType::widthSliderMoved(int) { 00200 if(p_widthSlider->value() <= p_offsetSlider->value()) 00201 p_widthSlider->setValue(p_offsetSlider->value() + 1); 00202 00203 if(p_sliderOverride) 00204 return; 00205 00206 double highVal = p_cubeHist->Maximum() - p_cubeHist->Minimum(); 00207 double lowVal = p_cubeHist->BinSize(); 00208 double value = lowVal + p_widthSlider->value() * 00209 (highVal - lowVal) / 1000.0; 00210 p_widthEdit->setText(QString::number(value)); 00211 } 00212 00213 00219 void SawtoothStretchType::widthEditChanged(const QString &) { 00220 double value = p_widthEdit->text().toDouble(); 00221 00222 double highVal = p_cubeHist->Maximum() - p_cubeHist->Minimum(); 00223 double lowVal = p_cubeHist->BinSize(); 00224 00225 double percentage = value - lowVal; 00226 percentage /= (highVal - lowVal); 00227 int valuePos = (int)(percentage * 1000.0); 00228 00229 p_sliderOverride = true; 00230 p_widthSlider->setValue(valuePos); 00231 p_sliderOverride = false; 00232 00233 Stretch newStretch = calculateNewStretch(); 00234 00235 if(newStretch.Text() != p_stretch->Text()) { 00236 p_stretch->CopyPairs(newStretch); 00237 emit stretchChanged(); 00238 } 00239 } 00240 00241 00253 Stretch SawtoothStretchType::calculateNewStretch(double offset, 00254 double width) { 00255 Stretch stretch; 00256 width = fabs(width); 00257 00258 if(width < p_cubeHist->BinSize()) 00259 width = p_cubeHist->BinSize(); 00260 00261 // Still can't do it? Give up 00262 if(width <= 0) return Stretch(); 00263 00264 bool high = false; 00265 00266 // We want leftPoint to be our starting point for the sawtooth, one left of 00267 // the minimum 00268 double leftPoint = offset; 00269 00270 // If leftPoint is too far left, move it right 00271 while(leftPoint < p_cubeHist->Minimum() - width) { 00272 leftPoint += width; 00273 high = !high; 00274 } 00275 00276 // If leftPoint is too far fight, move it left 00277 while(leftPoint >= p_cubeHist->Minimum()) { 00278 leftPoint -= width; 00279 high = !high; 00280 } 00281 00282 double currPoint = leftPoint; 00283 00284 bool terminated = false; 00285 while(!terminated) { 00286 int outValue = (high) ? 255 : 0; 00287 00288 // This conversion to a string & back prevents infinite loops due to 00289 // rounding errors and disagreements betweeen double to string 00290 // conversions later on (in setStretch) 00291 stretch.AddPair(QString::number(currPoint).toDouble(), outValue); 00292 00293 if(currPoint > p_cubeHist->Maximum()) { 00294 terminated = true; 00295 } 00296 00297 high = !high; 00298 currPoint += width; 00299 } 00300 00301 return stretch; 00302 } 00303 00304 00310 Stretch SawtoothStretchType::calculateNewStretch() { 00311 return calculateNewStretch(p_offsetEdit->text().toDouble(), 00312 p_widthEdit->text().toDouble()); 00313 } 00314 } 00315