From 2dc65096354b65221d5d4948a42ea0cb0a3168ff Mon Sep 17 00:00:00 2001 From: James Hogan Date: Sun, 7 Dec 2008 22:21:30 +0000 Subject: [PATCH] Fixed SRTM positioning (each tile overlaps the next by one sample) and added config widget to negative product --- NOTES | 1 + geo/CMakeLists.txt | 1 + geo/tcChannel.h | 3 +- geo/tcNegativeProduct.cpp | 84 +++++++++++++++++++++++++++++++++++++++++++---- geo/tcNegativeProduct.h | 39 ++++++++++++++++++++++ geo/tcSrtmData.cpp | 32 +++++++++--------- tcMainWindow.cpp | 1 + 7 files changed, 136 insertions(+), 25 deletions(-) diff --git a/NOTES b/NOTES index 574cddb..4ed98ba 100644 --- a/NOTES +++ b/NOTES @@ -64,6 +64,7 @@ Thursday 4th Dec fix list [ ] seems - not important [ ] when creating texture for region, don't up sample, select larger area +[ ] dem channels not updated when dem changes todo [X] proper texturing diff --git a/geo/CMakeLists.txt b/geo/CMakeLists.txt index c700171..78a249d 100644 --- a/geo/CMakeLists.txt +++ b/geo/CMakeLists.txt @@ -40,6 +40,7 @@ set(tecorrec_geo_SRCS set(tecorrec_geo_HEADERS tcChannelConfigWidget.h tcIlluminantDirection.h + tcNegativeProduct.h ) qt4_wrap_cpp(tecorrec_geo_MOCS ${tecorrec_geo_HEADERS}) diff --git a/geo/tcChannel.h b/geo/tcChannel.h index 5c272e3..02622e9 100644 --- a/geo/tcChannel.h +++ b/geo/tcChannel.h @@ -27,6 +27,7 @@ #include "tcPixelData.h" +#include #include #include @@ -35,7 +36,7 @@ class tcChannelConfigWidget; /// A single abstract image channel. -class tcChannel +class tcChannel : public QObject { public: diff --git a/geo/tcNegativeProduct.cpp b/geo/tcNegativeProduct.cpp index 2ccd0ff..5df8316 100644 --- a/geo/tcNegativeProduct.cpp +++ b/geo/tcNegativeProduct.cpp @@ -23,8 +23,14 @@ */ #include "tcNegativeProduct.h" +#include "tcChannelConfigWidget.h" -#include +#include +#include +#include +#include + +#include /* * Constructors + destructor @@ -32,9 +38,12 @@ /// Primary constructor. tcNegativeProduct::tcNegativeProduct(const QList& inputChannels) -: tcChannel(QObject::tr("Negative Product"), - QObject::tr("Highlights pixels which are dark in all channels")) +: tcChannel(tr("Negative Product"), + tr("Highlights pixels which are dark in all channels")) , m_inputChannels(inputChannels) +, m_thresholdEnabled(false) +, m_threshold(0.01f) +, m_configWidget(0) { Q_ASSERT(m_inputChannels.size() > 0); foreach (tcChannel* channel, m_inputChannels) @@ -50,6 +59,45 @@ tcNegativeProduct::~tcNegativeProduct() { channel->removeDerivitive(this); } + delete m_configWidget; +} + +/* + * Main image interface + */ + +tcChannelConfigWidget* tcNegativeProduct::configWidget() +{ + if (0 == m_configWidget) + { + m_configWidget = new tcChannelConfigWidget(); + m_configWidget->setWindowTitle(QObject::tr("%1 Configuration").arg(name())); + + QVBoxLayout* layout = new QVBoxLayout(m_configWidget); + + // Create a checkbox to enable/disable threshold. + QCheckBox* chkThreshold = new QCheckBox(tr("Threshold to classify shadow"), m_configWidget); + layout->addWidget(chkThreshold); + chkThreshold->setCheckState(m_thresholdEnabled ? Qt::Checked : Qt::Unchecked); + connect(chkThreshold, SIGNAL(clicked(bool)), this, SLOT(setThresholdEnabled(bool))); + + // Create a slider to set threshold. + QSlider* sliderThreshold = new QSlider(Qt::Horizontal, m_configWidget); + layout->addWidget(sliderThreshold); + sliderThreshold->setRange(-200, 0); + sliderThreshold->setValue(sliderThreshold->minimum()); + connect(sliderThreshold, SIGNAL(valueChanged(int)), this, SLOT(setThreshold(int))); + connect(chkThreshold, SIGNAL(clicked(bool)), sliderThreshold, SLOT(setEnabled(bool))); + + // Label to tell us what the threshold is. + QLabel* labelThreshold = new QLabel(m_configWidget); + layout->addWidget(labelThreshold); + connect(this, SIGNAL(thresholdChanged(const QString&)), labelThreshold, SLOT(setText(const QString&))); + connect(chkThreshold, SIGNAL(clicked(bool)), labelThreshold, SLOT(setEnabled(bool))); + + setThreshold(sliderThreshold->value()); + } + return m_configWidget; } /* @@ -94,12 +142,13 @@ tcAbstractPixelData* tcNegativeProduct::loadPortion(double x1, double y1, double data->buffer()[i] *= 1.0f - (float)channelData->buffer()[i] / 255.0f; } } -#if 0 - if (0 != data) + + // Threshold + if (0 != data && m_thresholdEnabled) { for (int i = 0; i < width*height; ++i) { - if (data->buffer()[i] > 0.01f) + if (data->buffer()[i] > m_threshold) { data->buffer()[i] = 0.0f; } @@ -109,6 +158,27 @@ tcAbstractPixelData* tcNegativeProduct::loadPortion(double x1, double y1, double } } } -#endif + return data; } + +/* + * Private slots + */ + +/// Set whether the theshold is enabled. +void tcNegativeProduct::setThresholdEnabled(bool thresholdEnabled) +{ + m_thresholdEnabled = thresholdEnabled; + invalidate(); + m_configWidget->requestRedraw(); +} + +/// Set the theshold value. +void tcNegativeProduct::setThreshold(int threshold) +{ + m_threshold = exp((float)threshold/10); + invalidate(); + m_configWidget->requestRedraw(); + emit thresholdChanged(tr("Threshold: %1").arg(m_threshold)); +} diff --git a/geo/tcNegativeProduct.h b/geo/tcNegativeProduct.h index 2c4252e..ec3ec37 100644 --- a/geo/tcNegativeProduct.h +++ b/geo/tcNegativeProduct.h @@ -32,6 +32,8 @@ /// Highlights the parts of an image which are dark in all channels. class tcNegativeProduct : public tcChannel { + Q_OBJECT + public: /* @@ -44,6 +46,13 @@ class tcNegativeProduct : public tcChannel /// Destructor. virtual ~tcNegativeProduct(); + /* + * Main image interface + */ + + // Reimplemented + virtual tcChannelConfigWidget* configWidget(); + protected: /* @@ -56,6 +65,27 @@ class tcNegativeProduct : public tcChannel // Reimplemented virtual tcAbstractPixelData* loadPortion(double x1, double y1, double x2, double y2); + signals: + + /* + * Signals + */ + + /// Emitted when the threshold text changes. + void thresholdChanged(const QString& threshold); + + private slots: + + /* + * Private slots + */ + + /// Set whether the theshold is enabled. + void setThresholdEnabled(bool thresholdEnabled); + + /// Set the theshold value. + void setThreshold(int threshold); + private: /* @@ -64,6 +94,15 @@ class tcNegativeProduct : public tcChannel /// Input channels. QList m_inputChannels; + + /// Whether threshold is enabled. + bool m_thresholdEnabled; + + /// Threshold to classify shadows. + float m_threshold; + + /// Configuration widget. + tcChannelConfigWidget* m_configWidget; }; #endif diff --git a/geo/tcSrtmData.cpp b/geo/tcSrtmData.cpp index 06aa789..20fd025 100644 --- a/geo/tcSrtmData.cpp +++ b/geo/tcSrtmData.cpp @@ -105,15 +105,15 @@ int tcSrtmData::samples() const /// Find the geographical angles between samples. tcGeo tcSrtmData::sampleResolution() const { - return tcGeo(M_PI/180 / m_samples, - M_PI/180 / m_lines); + return tcGeo(M_PI/180 / (m_samples - 1), + M_PI/180 / (m_lines - 1)); } /// Get the geographical coordinate of a sample. tcGeo tcSrtmData::sampleCoordinate(int line, int sample) const { - return tcGeo(M_PI/180*((double)m_lon + (double)sample/m_samples), - M_PI/180*((double)(m_lat+1) - (double)line /m_lines )); + return tcGeo(M_PI/180*((double) m_lon + (double)sample/(m_samples-1)), + M_PI/180*((double)(m_lat+1) - (double)line /(m_lines -1))); } /// Does data exist for a sample? @@ -143,28 +143,26 @@ float tcSrtmData::sampleAltitude(const tcGeo& coord, bool corrected, bool* exist double dlat = coord.lat()*180.0/M_PI - m_lat; Q_ASSERT(dlon >= 0.0 && dlon < 1.0); Q_ASSERT(dlat >= 0.0 && dlat < 1.0); - int line = (int)floor(dlat*m_lines); - float dy = dlat*m_lines - line; + int line = (int)floor(dlat*(m_lines-1)); + float dy = dlat*(m_lines-1) - line; line = m_lines - 1 - line; - int sample = (int)floor(dlon*m_samples); - float dx = dlon*m_samples - sample; - Q_ASSERT(line >= 0 && line < m_lines); - Q_ASSERT(sample >= 0 && sample < m_samples); + int sample = (int)floor(dlon*(m_samples-1)); + float dx = dlon*(m_samples-1) - sample; + Q_ASSERT(line > 0 && line < m_lines); + Q_ASSERT(sample >= 0 && sample < m_samples-1); Q_ASSERT(dx >= 0.0f && dx <= 1.0f); Q_ASSERT(dy >= 0.0f && dy <= 1.0f); if (0 != exists) { *exists = (0x0000 == (0x8000 & m_data[indexData(corrected ? 1 : 0, line, sample)])); } - bool endX = (sample == m_samples-1); - bool endY = (line == m_lines -1); - uint16_t x00 = (0x7FFF & m_data[indexData(corrected ? 1 : 0, line, sample )]); - uint16_t x10 = (endX ? x00 : (0x7FFF & m_data[indexData(corrected ? 1 : 0, line, sample+1)])); - uint16_t x01 = (endY ? x00 : (0x7FFF & m_data[indexData(corrected ? 1 : 0, line+1, sample )])); - uint16_t x11 = ((endX || endY) ? x10 : (0x7FFF & m_data[indexData(corrected ? 1 : 0, line+1, sample+1)])); + uint16_t x00 = 0x7FFF & m_data[indexData(corrected ? 1 : 0, line, sample )]; + uint16_t x10 = 0x7FFF & m_data[indexData(corrected ? 1 : 0, line, sample+1)]; + uint16_t x01 = 0x7FFF & m_data[indexData(corrected ? 1 : 0, line-1, sample )]; + uint16_t x11 = 0x7FFF & m_data[indexData(corrected ? 1 : 0, line-1, sample+1)]; float mdx = 1.0f-dx; float mdy = 1.0f-dy; - return ((float)x00*(mdx + dy) + (float)x01*(mdx + mdy) + (float)x10*(dx + dy) + (float)x11*(dx + mdy)) / 4.0; + return ((float)x00*(mdx + mdy) + (float)x01*(mdx + dy) + (float)x10*(dx + mdy) + (float)x11*(dx + dy)) / 4.0; } /* diff --git a/tcMainWindow.cpp b/tcMainWindow.cpp index a499016..b63ce3c 100644 --- a/tcMainWindow.cpp +++ b/tcMainWindow.cpp @@ -205,6 +205,7 @@ void tcMainWindow::configureChannel(int channel) m_viewport, SLOT(updateGL())); connect(configWidget, SIGNAL(texturePointRequested(QObject*, const char*)), m_viewport, SLOT(texturePointMode(QObject*, const char*))); + configWidget->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); configWidget->show(); } } -- 2.11.4.GIT