USGS

Isis 3.0 Object Programmers' Reference

Home

BinaryStretchType.cpp

00001 #include "BinaryStretchType.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   BinaryStretchType::BinaryStretchType(const Histogram &hist,
00024                                        const Stretch &stretch,
00025                                        const QString &name, const QColor &color)
00026     : StretchType(hist, stretch, name, color) {
00027     p_startSlider = NULL;
00028     p_startEdit = NULL;
00029     p_endSlider = NULL;
00030     p_endEdit = NULL;
00031     p_sliderOverride = false;
00032     p_editOverride = false;
00033 
00034     QWidget *sliderWidget = new QWidget();
00035     QGridLayout *sliderLayout = new QGridLayout();
00036     sliderLayout->setColumnStretch(1, 10);
00037 
00038     QLabel *startLabel = new QLabel("Start");
00039     p_startSlider = new QSlider(Qt::Horizontal);
00040     p_startSlider->setTickPosition(QSlider::NoTicks);
00041     p_startSlider->setMinimum(0);
00042     p_startSlider->setMaximum(1000);
00043     p_startSlider->setPageStep(50);
00044     connect(p_startSlider, SIGNAL(valueChanged(int)),
00045             this, SLOT(startSliderMoved(int)));
00046     p_startEdit = new QLineEdit();
00047     p_startEdit->setMaximumWidth(75);
00048     p_startEdit->setText(QString::number(p_cubeHist->Percent(25)));
00049     connect(p_startEdit, SIGNAL(textChanged(const QString &)),
00050             this, SLOT(startEditChanged(const QString &)));
00051     sliderLayout->addWidget(startLabel,  0, 0);
00052     sliderLayout->addWidget(p_startSlider, 0, 1);
00053     sliderLayout->addWidget(p_startEdit,   0, 2);
00054 
00055     QLabel *endLabel = new QLabel("End");
00056     p_endSlider = new QSlider(Qt::Horizontal);
00057     p_endSlider->setTickPosition(QSlider::NoTicks);
00058     p_endSlider->setMinimum(0);
00059     p_endSlider->setMaximum(1000);
00060     p_endSlider->setValue(1000);
00061     p_endSlider->setPageStep(50);
00062     connect(p_endSlider, SIGNAL(valueChanged(int)),
00063             this, SLOT(endSliderMoved(int)));
00064     p_endEdit = new QLineEdit();
00065     p_endEdit->setMaximumWidth(75);
00066     p_endEdit->setText(QString::number(p_cubeHist->Percent(75)));
00067     connect(p_endEdit, SIGNAL(textChanged(const QString &)),
00068             this, SLOT(endEditChanged(const QString &)));
00069     sliderLayout->addWidget(endLabel,  1, 0);
00070     sliderLayout->addWidget(p_endSlider, 1, 1);
00071     sliderLayout->addWidget(p_endEdit,   1, 2);
00072 
00073     sliderWidget->setLayout(sliderLayout);
00074     p_mainLayout->addWidget(sliderWidget, 1, 0);
00075 
00076     setLayout(p_mainLayout);
00077     setStretch(calculateNewStretch());
00078   }
00079 
00080 
00084   BinaryStretchType::~BinaryStretchType() {
00085   }
00086 
00087 
00099   void BinaryStretchType::setStretch(Stretch newStretch) {
00100     double epsilon = p_cubeHist->BinSize();
00101 
00102     Stretch interpretted;
00103 
00104     double switch1 = 0.0;
00105     double switch2 = 1.0;
00106 
00107     if(newStretch.Pairs() == 2) {
00108       // given a flat line?
00109       if(newStretch.Output(0) == newStretch.Output(1)) {
00110         // assume its binary all white
00111         interpretted.AddPair(p_cubeHist->Minimum(), 255);
00112         interpretted.AddPair(p_cubeHist->Maximum(), 255);
00113       }
00114       else {
00115         // probably linear, figure out something reasonable
00116         interpretted.AddPair(p_cubeHist->Minimum(), 0);
00117 
00118         switch1 = newStretch.Input(0);
00119         if(switch1 < p_cubeHist->Minimum())
00120           switch1 = p_cubeHist->Minimum() + epsilon;
00121 
00122         interpretted.AddPair(switch1, 0);
00123         interpretted.AddPair(switch1 + epsilon, 255);
00124 
00125         switch2 = newStretch.Input(1);
00126         if(switch2 <= switch1 + epsilon)
00127           switch2 = switch1 + epsilon + epsilon;
00128 
00129         interpretted.AddPair(switch2, 255);
00130         interpretted.AddPair(switch2 + epsilon, 0);
00131 
00132         double end = p_cubeHist->Maximum();
00133         if(end <= switch2 + epsilon)
00134           end = switch2 + epsilon + epsilon;
00135 
00136         interpretted.AddPair(end, 0);
00137       }
00138     }
00139     else if(newStretch.Pairs() == 4) {
00140       if(newStretch.Output(0) > 127) {
00141         interpretted.AddPair(p_cubeHist->Minimum(), 255);
00142 
00143         switch1 = newStretch.Input(1);
00144         if(switch1 <= p_cubeHist->Minimum())
00145           switch1 = p_cubeHist->Minimum() + epsilon;
00146 
00147         interpretted.AddPair(switch1, 255);
00148         interpretted.AddPair(switch1 + epsilon, 0);
00149 
00150         double end = p_cubeHist->Maximum();
00151         if(end <= switch1 + epsilon)
00152           end = switch1 + epsilon + epsilon;
00153 
00154         switch2 = end;
00155 
00156         interpretted.AddPair(end, 0);
00157       }
00158       else {
00159         interpretted.AddPair(p_cubeHist->Minimum(), 0);
00160 
00161         switch1 = newStretch.Input(1);
00162         if(switch1 < p_cubeHist->Minimum())
00163           switch1 = p_cubeHist->Minimum() + epsilon;
00164 
00165         interpretted.AddPair(switch1, 0);
00166         interpretted.AddPair(switch1 + epsilon, 255);
00167 
00168         double end = p_cubeHist->Maximum();
00169         if(end <= switch1 + epsilon)
00170           end = switch1 + epsilon + epsilon;
00171         switch2 = end;
00172 
00173         interpretted.AddPair(end, 255);
00174       }
00175     }
00176     // 6 pairs means the 255 values are in the middle (typical)
00177     else if(newStretch.Pairs() == 6) {
00178       interpretted.AddPair(p_cubeHist->Minimum(), 0);
00179 
00180       switch1 = newStretch.Input(1);
00181       if(switch1 <= p_cubeHist->Minimum())
00182         switch1 = p_cubeHist->Minimum() + epsilon;
00183 
00184       interpretted.AddPair(switch1, 0);
00185       interpretted.AddPair(switch1 + epsilon, 255);
00186 
00187 
00188       switch2 = newStretch.Input(3);
00189       if(switch2 <= switch1 + epsilon)
00190         switch2 = switch1 + epsilon + epsilon;
00191 
00192       interpretted.AddPair(switch2, 255);
00193       interpretted.AddPair(switch2 + epsilon, 0);
00194 
00195       double end = p_cubeHist->Maximum();
00196       if(end <= switch2 + epsilon)
00197         end = switch2 + epsilon + epsilon;
00198 
00199       interpretted.AddPair(end, 0);
00200     }
00201 
00202     if(!interpretted.Pairs()) {
00203       interpretted.CopyPairs(calculateNewStretch());
00204       switch1 = p_startEdit->text().toDouble();
00205       switch2 = p_endEdit->text().toDouble();
00206     }
00207 
00208     bool changed = (interpretted.Text() != p_stretch->Text());
00209 
00210     p_editOverride = true;
00211     if(changed) {
00212       p_stretch->CopyPairs(interpretted);
00213       p_startEdit->setText(QString::number(switch1));
00214       p_endEdit->setText(QString::number(switch2));
00215     }
00216 
00217     // regardless of it all, slider positions could need changed...
00218     startEditChanged(QString());
00219     endEditChanged(QString());
00220     p_editOverride = false;
00221 
00222     if(changed) {
00223       emit stretchChanged();
00224     }
00225   }
00226 
00227 
00232   void BinaryStretchType::startSliderMoved(int) {
00233     if(p_sliderOverride)
00234       return;
00235 
00236     if(p_startSlider->value() >= p_endSlider->value()) {
00237       p_startSlider->setValue(p_endSlider->value() - 1);
00238       return;
00239     }
00240 
00241     double value = p_cubeHist->Minimum();
00242     value += p_startSlider->value() *
00243              (p_cubeHist->Maximum() - p_cubeHist->Minimum()) / 1000.0;
00244     p_startEdit->setText(QString::number(value));
00245   }
00246 
00247 
00252   void BinaryStretchType::startEditChanged(const QString &) {
00253     double value = p_startEdit->text().toDouble();
00254 
00255     if(value >= p_endEdit->text().toDouble()) {
00256       return;
00257     }
00258 
00259     double percentage = value - p_cubeHist->Minimum();
00260     percentage /= (p_cubeHist->Maximum() - p_cubeHist->Minimum());
00261     int valuePos = (int)(percentage * 1000.0);
00262 
00263     p_sliderOverride = true;
00264     p_startSlider->setValue(valuePos);
00265     p_sliderOverride = false;
00266 
00267     if(p_editOverride) return;
00268 
00269     Stretch newStretch = calculateNewStretch();
00270 
00271     if(newStretch.Text() != p_stretch->Text()) {
00272       p_stretch->CopyPairs(newStretch);
00273       emit stretchChanged();
00274     }
00275   }
00276 
00277 
00282   void BinaryStretchType::endSliderMoved(int) {
00283     if(p_sliderOverride)
00284       return;
00285 
00286     if(p_endSlider->value() <= p_startSlider->value()) {
00287       p_endSlider->setValue(p_startSlider->value() + 1);
00288       return;
00289     }
00290 
00291     double value = p_cubeHist->Minimum();
00292     value += p_endSlider->value() *
00293              (p_cubeHist->Maximum() - p_cubeHist->Minimum()) / 1000.0;
00294     p_endEdit->setText(QString::number(value));
00295   }
00296 
00297 
00302   void BinaryStretchType::endEditChanged(const QString &) {
00303     double value = p_endEdit->text().toDouble();
00304 
00305     if(value <= p_startEdit->text().toDouble()) {
00306       return;
00307     }
00308 
00309     double percentage = value - p_cubeHist->Minimum();
00310     percentage /= (p_cubeHist->Maximum() - p_cubeHist->Minimum());
00311     int valuePos = (int)(percentage * 1000.0);
00312 
00313     p_sliderOverride = true;
00314     p_endSlider->setValue(valuePos);
00315     p_sliderOverride = false;
00316 
00317     if(p_editOverride) return;
00318 
00319     Stretch newStretch = calculateNewStretch();
00320 
00321     if(newStretch.Text() != p_stretch->Text()) {
00322       p_stretch->CopyPairs(newStretch);;
00323       emit stretchChanged();
00324     }
00325   }
00326 
00327 
00334   Stretch BinaryStretchType::calculateNewStretch() {
00335     double epsilon = p_cubeHist->BinSize();
00336 
00337     if(epsilon == 0) {
00338       epsilon = (p_cubeHist->Maximum() - p_cubeHist->Minimum()) / 65536;
00339     }
00340 
00341     Stretch newStretch;
00342 
00343     if(epsilon == 0) {
00344       return newStretch;
00345     }
00346     // Start high?
00347     double startPt = p_startEdit->text().toDouble();
00348     if(fabs(startPt - p_cubeHist->Minimum()) < epsilon ||
00349         startPt <= p_cubeHist->Minimum()) {
00350       newStretch.AddPair(p_cubeHist->Minimum(), 255);
00351       startPt = p_cubeHist->Minimum() - epsilon;
00352     }
00353     else {
00354       newStretch.AddPair(p_cubeHist->Minimum(), 0);
00355       newStretch.AddPair(startPt, 0);
00356       newStretch.AddPair(startPt + epsilon, 255);
00357     }
00358 
00359     // End high?
00360     double endPt = p_endEdit->text().toDouble();
00361     if(endPt <= startPt + epsilon) {
00362       endPt = startPt + 2 * epsilon;
00363     }
00364 
00365     if(fabs(endPt + epsilon - p_cubeHist->Maximum()) < epsilon ||
00366         endPt + epsilon >= p_cubeHist->Maximum()) {
00367       newStretch.AddPair(p_cubeHist->Maximum(), 255);
00368     }
00369     else {
00370       newStretch.AddPair(endPt, 255);
00371       newStretch.AddPair(endPt + epsilon, 0);
00372       newStretch.AddPair(p_cubeHist->Maximum(), 0);
00373     }
00374 
00375     return newStretch;
00376   }
00377 }