From e02912c012c048a7de2655393c056aa02b14390a Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 8 Dec 2008 01:16:40 +0000 Subject: [PATCH] Improve feedback by writing progress to status bar for various operations --- geo/CMakeLists.txt | 3 +++ geo/tcChannel.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++ geo/tcChannel.h | 37 ++++++++++++++++++++++++++++++ geo/tcChannelChromaticity.cpp | 22 ++++++++++-------- geo/tcChannelManager.cpp | 7 +++++- geo/tcChannelManager.h | 14 +++++++++++- geo/tcGlobe.cpp | 8 ++++++- geo/tcGlobe.h | 3 +++ geo/tcLambertianShading.cpp | 3 +++ geo/tcLandsatData.cpp | 36 +++++++++++++++++------------- geo/tcNegativeProduct.cpp | 15 ++++++------- geo/tcPixelData.h | 13 +++++++++++ geo/tcRaytracedShadowMap.cpp | 3 +++ geo/tcSrtmCache.cpp | 2 +- geo/tcSrtmCache.h | 14 +++++++++++- geo/tcSrtmData.cpp | 14 +++++++++++- geo/tcSrtmData.h | 18 +++++++++++++-- geo/tcSrtmModel.cpp | 4 ++++ geo/tcSrtmModel.h | 3 +++ tcMainWindow.cpp | 6 ++++- 20 files changed, 235 insertions(+), 42 deletions(-) diff --git a/geo/CMakeLists.txt b/geo/CMakeLists.txt index 374fc9c..37579fc 100644 --- a/geo/CMakeLists.txt +++ b/geo/CMakeLists.txt @@ -40,10 +40,13 @@ set(tecorrec_geo_SRCS set(tecorrec_geo_HEADERS tcChannel.h tcChannelGroup.h + tcChannelManager.h tcChannelConfigWidget.h tcIlluminantDirection.h tcNegativeProduct.h tcSrtmModel.h + tcSrtmCache.h + tcSrtmData.h ) qt4_wrap_cpp(tecorrec_geo_MOCS ${tecorrec_geo_HEADERS}) diff --git a/geo/tcChannel.cpp b/geo/tcChannel.cpp index e09582b..13fdf86 100644 --- a/geo/tcChannel.cpp +++ b/geo/tcChannel.cpp @@ -25,6 +25,16 @@ #include "tcChannel.h" /* + * Static variables + */ + +/// Current processing step. +QString tcChannel::s_processingStep; + +/// Last progress percent. +int tcChannel::s_processingLastPercent; + +/* * Constructors + destructor */ @@ -160,3 +170,45 @@ void tcChannel::invalidate() derivitive->invalidate(); } } + +/* + * Progress functions + */ + +/// Start a processing step. +void tcChannel::startProcessing(const QString& step) +{ + if (step.isEmpty()) + { + s_processingStep = step; + } + else + { + s_processingStep = step + ": "; + } + s_processingLastPercent = -1; + emit progressing(tr("%1: %2").arg(name()).arg(s_processingStep)); +} + +/// Update progress. +void tcChannel::progress(float progress) +{ + int percent = progress*100.0f; + if (percent != s_processingLastPercent) + { + s_processingLastPercent = percent; + emit progressing(tr("%1: %2%3%").arg(name()).arg(s_processingStep).arg(percent)); + } +} + +/// Update progress. +void tcChannel::progress(const QString& info) +{ + emit progressing(tr("%1: %2%3").arg(name()).arg(s_processingStep).arg(info)); +} + +/// End processing step. +void tcChannel::endProcessing() +{ + emit progressing(tr("%1: %2Complete").arg(name()).arg(s_processingStep)); +} diff --git a/geo/tcChannel.h b/geo/tcChannel.h index 2d9a92c..f73aab7 100644 --- a/geo/tcChannel.h +++ b/geo/tcChannel.h @@ -120,6 +120,33 @@ class tcChannel : public QObject */ void invalidate(); + signals: + + /* + * Signals + */ + + /// Emitted to indicate progress of processing. + void progressing(const QString& message); + + protected: + + /* + * Progress functions + */ + + /// Start a processing step. + void startProcessing(const QString& step); + + /// Update progress. + void progress(float progress); + + /// Update progress. + void progress(const QString& info); + + /// End processing step. + void endProcessing(); + private: /* @@ -140,6 +167,16 @@ class tcChannel : public QObject /// Portion coordinates. double m_portionPosition[2][2]; + + /* + * Static variables + */ + + /// Current processing step. + static QString s_processingStep; + + /// Last progress percent. + static int s_processingLastPercent; }; #endif diff --git a/geo/tcChannelChromaticity.cpp b/geo/tcChannelChromaticity.cpp index 003aea4..eb13abc 100644 --- a/geo/tcChannelChromaticity.cpp +++ b/geo/tcChannelChromaticity.cpp @@ -67,18 +67,22 @@ tcAbstractPixelData* tcChannelChromaticity::loadPortion(double x1, double y1, do { int width = numerator->width(); int height = numerator->height(); - Q_ASSERT(width == denominator->width()); - Q_ASSERT(height == denominator->height()); data = new tcPixelData(width, height); - for (int i = 0; i < width*height; ++i) + for (int j = 0; j < height; ++j) { - if (numerator->buffer()[i] != 0xff && denominator->buffer()[i] != 0xff && denominator->buffer()[i] != 0x00) + for (int i = 0; i < width; ++i) { - data->buffer()[i] = (double)numerator->buffer()[i] / denominator->buffer()[i]; - } - else - { - data->buffer()[i] = 0.0f; + int index = j*width + i; + GLubyte n = numerator->buffer()[index]; + GLubyte d = numerator->sampleUByte((float)i/(width-1), (float)j/(height-1)); + if (n != 0xff && d != 0xff && d != 0x00) + { + data->buffer()[index] = (float)n / d; + } + else + { + data->buffer()[index] = 0.0f; + } } } } diff --git a/geo/tcChannelManager.cpp b/geo/tcChannelManager.cpp index d72ba88..024ddde 100644 --- a/geo/tcChannelManager.cpp +++ b/geo/tcChannelManager.cpp @@ -23,6 +23,7 @@ */ #include "tcChannelManager.h" +#include "tcChannel.h" /* * Constructors + destructor @@ -63,11 +64,15 @@ tcChannel* tcChannelManager::channel(int index) const int tcChannelManager::addChannel(tcChannel* channel) { m_channels += channel; + connect(channel, SIGNAL(progressing(const QString&)), this, SIGNAL(progressing(const QString&))); return m_channels.size()-1; } /// Add and take ownership of a set of channels. void tcChannelManager::addChannels(const QList& channels) { - m_channels += channels; + foreach (tcChannel* channel, channels) + { + addChannel(channel); + } } diff --git a/geo/tcChannelManager.h b/geo/tcChannelManager.h index 74928c0..22b3457 100644 --- a/geo/tcChannelManager.h +++ b/geo/tcChannelManager.h @@ -25,13 +25,16 @@ * @brief Manages a set of channels, any of which can be mapped to RGB. */ +#include #include class tcChannel; /// Manages a set of channels, any of which can be mapped to RGB. -class tcChannelManager +class tcChannelManager : public QObject { + Q_OBJECT + public: /* @@ -64,6 +67,15 @@ class tcChannelManager /// Add and take ownership of a set of channels. void addChannels(const QList& channels); + signals: + + /* + * Signals + */ + + /// Emitted to indicate progress of processing. + void progressing(const QString& message); + private: /* diff --git a/geo/tcGlobe.cpp b/geo/tcGlobe.cpp index c06d1cd..4046775 100644 --- a/geo/tcGlobe.cpp +++ b/geo/tcGlobe.cpp @@ -42,7 +42,7 @@ tcGlobe::tcGlobe(double meanRadius) : m_meanRadius(meanRadius) , m_elevation(new tcSrtmModel()) , m_imagery(0) -, m_elevationMode(RawElevation) +, m_elevationMode(CorrectedElevation) , m_elevationCorrection(0.0f) , m_colourCoding(NoColourCoding) , m_colourMapping() @@ -76,6 +76,12 @@ tcGeoImageData* tcGlobe::imagery() const return m_imagery; } +/// Get the elevation model. +tcSrtmModel* tcGlobe::dem() const +{ + return m_elevation; +} + /* * Rendering */ diff --git a/geo/tcGlobe.h b/geo/tcGlobe.h index 442cae5..8316054 100644 --- a/geo/tcGlobe.h +++ b/geo/tcGlobe.h @@ -76,6 +76,9 @@ class tcGlobe /// Get the imagery data. tcGeoImageData* imagery() const; + /// Get the elevation model. + tcSrtmModel* dem() const; + /* * Rendering */ diff --git a/geo/tcLambertianShading.cpp b/geo/tcLambertianShading.cpp index 078e234..f0717d4 100644 --- a/geo/tcLambertianShading.cpp +++ b/geo/tcLambertianShading.cpp @@ -63,8 +63,10 @@ tcAbstractPixelData* tcLambertianShading::loadPortion(double x1, double y1, doub // Create a new pixel buffer tcPixelData* data = new tcPixelData(width, height); + startProcessing("Calculating lighting"); for (int j = 0; j < height; ++j) { + progress((float)j/(height-1)); for (int i = 0; i < width; ++i) { int index = j*width + i; @@ -81,5 +83,6 @@ tcAbstractPixelData* tcLambertianShading::loadPortion(double x1, double y1, doub data->buffer()[index] = (lambert >= 0.0f ? lambert : 0.0f); } } + endProcessing(); return data; } diff --git a/geo/tcLandsatData.cpp b/geo/tcLandsatData.cpp index f8d8b8c..99b7443 100644 --- a/geo/tcLandsatData.cpp +++ b/geo/tcLandsatData.cpp @@ -142,33 +142,37 @@ tcLandsatData::tcLandsatData(const QString& path, tcSrtmModel* dem) mainColourChannels += channelManager()->channel(2); mainColourChannels += channelManager()->channel(3); mainColourChannels += channelManager()->channel(4); + mainColourChannels += channelManager()->channel(5); + mainColourChannels += channelManager()->channel(6); mainColourChannels += channelManager()->channel(7); + mainColourChannels += channelManager()->channel(8); tcNegativeProduct* np = new tcNegativeProduct(mainColourChannels); channelManager()->addChannel(np); + tcLambertianShading* diffuse = new tcLambertianShading(channelManager()->channel(0), dem, this); + channelManager()->addChannel(diffuse); + tcRaytracedShadowMap* raytrace = new tcRaytracedShadowMap(channelManager()->channel(0), dem, this); + channelManager()->addChannel(raytrace); + QList chromaticities; - chromaticities += new tcChannelChromaticity(channelManager()->channel(0), channelManager()->channel(4)); - chromaticities += new tcChannelChromaticity(channelManager()->channel(1), channelManager()->channel(4)); - chromaticities += new tcChannelChromaticity(channelManager()->channel(2), channelManager()->channel(4)); - chromaticities += new tcChannelChromaticity(channelManager()->channel(3), channelManager()->channel(4)); - chromaticities += new tcChannelChromaticity(channelManager()->channel(4), channelManager()->channel(4)); - chromaticities += new tcChannelChromaticity(channelManager()->channel(7), channelManager()->channel(4)); - foreach (tcChannel* channel, chromaticities) - { - channelManager()->addChannel(channel); - } + chromaticities += new tcChannelChromaticity(channelManager()->channel(0), channelManager()->channel(8)); + chromaticities += new tcChannelChromaticity(channelManager()->channel(1), channelManager()->channel(8)); + chromaticities += new tcChannelChromaticity(channelManager()->channel(2), channelManager()->channel(8)); + chromaticities += new tcChannelChromaticity(channelManager()->channel(3), channelManager()->channel(8)); + chromaticities += new tcChannelChromaticity(channelManager()->channel(4), channelManager()->channel(8)); + chromaticities += new tcChannelChromaticity(channelManager()->channel(5), channelManager()->channel(8)); + chromaticities += new tcChannelChromaticity(channelManager()->channel(6), channelManager()->channel(8)); + chromaticities += new tcChannelChromaticity(channelManager()->channel(7), channelManager()->channel(8)); + channelManager()->addChannels(chromaticities); + + /* tcShadowFreeChromaticities* sfc = new tcShadowFreeChromaticities(chromaticities); channelManager()->addChannels(sfc->channels()); tcIlluminantDiscontinuity* idm = new tcIlluminantDiscontinuity(chromaticities); channelManager()->addChannels(idm->channels()); tcShadowClassification* sc = new tcShadowClassification(idm, channelManager()->channel(4)); channelManager()->addChannel(sc); - - tcLambertianShading* diffuse = new tcLambertianShading(channelManager()->channel(0), dem, this); - channelManager()->addChannel(diffuse); - - tcRaytracedShadowMap* raytrace = new tcRaytracedShadowMap(channelManager()->channel(0), dem, this); - channelManager()->addChannel(raytrace); + */ // Only load one metafile break; diff --git a/geo/tcNegativeProduct.cpp b/geo/tcNegativeProduct.cpp index 465e1b6..29d01fd 100644 --- a/geo/tcNegativeProduct.cpp +++ b/geo/tcNegativeProduct.cpp @@ -130,16 +130,15 @@ tcAbstractPixelData* tcNegativeProduct::loadPortion(double x1, double y1, double data->buffer()[i] = 1.0f; } } - else - { - Q_ASSERT(channelData->width() == width); - Q_ASSERT(channelData->height() == height); - } // Go through channels clearing saturated pixels - for (int i = 0; i < width*height; ++i) + for (int j = 0; j < height; ++j) { - // Multiply by 1-value - data->buffer()[i] *= 1.0f - (float)channelData->buffer()[i] / 255.0f; + for (int i = 0; i < width; ++i) + { + int index = j*width + i; + // Multiply by 1-value + data->buffer()[index] *= 1.0f - (float)channelData->sampleUByte((float)i/(width-1), (float)j/(height-1)) / 255.0f; + } } } diff --git a/geo/tcPixelData.h b/geo/tcPixelData.h index ba94d0d..c31de37 100644 --- a/geo/tcPixelData.h +++ b/geo/tcPixelData.h @@ -71,6 +71,9 @@ class tcAbstractPixelData : public ReferenceCounted /// Discard of any cached texture id for this image. void discardTexture(); + /// Sample a byte value from the image. + virtual GLubyte sampleUByte(float x, float y) const = 0; + /// Sample a floating point value from the image. virtual float sampleFloat(float x, float y) const = 0; @@ -137,6 +140,16 @@ class tcPixelData : public tcAbstractPixelData } // Reimplemented + virtual GLubyte sampleUByte(float x, float y) const + { + if (x < 0.0) x = 0.0; + if (x > 1.0) x = 1.0; + if (y < 0.0) y = 0.0; + if (y > 1.0) y = 1.0; + return (GLubyte)m_data[(int)(y*(height()-1))*width() + (int)(x*(width()-1))]; + } + + // Reimplemented virtual float sampleFloat(float x, float y) const { if (x < 0.0) x = 0.0; diff --git a/geo/tcRaytracedShadowMap.cpp b/geo/tcRaytracedShadowMap.cpp index c185bcd..de536c7 100644 --- a/geo/tcRaytracedShadowMap.cpp +++ b/geo/tcRaytracedShadowMap.cpp @@ -61,8 +61,10 @@ tcAbstractPixelData* tcRaytracedShadowMap::loadPortion(double x1, double y1, dou // Create a new pixel buffer tcPixelData* data = new tcPixelData(width, height); + startProcessing(tr("Raytracing")); for (int j = 0; j < height; ++j) { + progress((float)j/(height-1)); for (int i = 0; i < width; ++i) { int index = j*width + i; @@ -75,5 +77,6 @@ tcAbstractPixelData* tcRaytracedShadowMap::loadPortion(double x1, double y1, dou data->buffer()[index] = lit; } } + endProcessing(); return data; } diff --git a/geo/tcSrtmCache.cpp b/geo/tcSrtmCache.cpp index 78e30da..f35a387 100644 --- a/geo/tcSrtmCache.cpp +++ b/geo/tcSrtmCache.cpp @@ -99,7 +99,7 @@ tcSrtmData* tcSrtmCache::loadData(int lon, int lat) QFile file(filename); if (file.open(QIODevice::ReadOnly)) { - cacheItem = new tcSrtmData(lon, lat, file); + cacheItem = new tcSrtmData(lon, lat, file, this, SIGNAL(progressing(const QString&))); } else { diff --git a/geo/tcSrtmCache.h b/geo/tcSrtmCache.h index 84adca9..5c05ba2 100644 --- a/geo/tcSrtmCache.h +++ b/geo/tcSrtmCache.h @@ -25,6 +25,7 @@ * @brief Manages cache of SRTM data. */ +#include #include #include #include @@ -37,8 +38,10 @@ class tcGeo; * * FTP site: ftp://e0srp01u.ecs.nasa.gov/ */ -class tcSrtmCache +class tcSrtmCache : public QObject { + Q_OBJECT + public: /* @@ -84,6 +87,15 @@ class tcSrtmCache */ tcSrtmData* findData(const tcGeo& swCorner, const tcGeo& neCorner); + signals: + + /* + * Signals + */ + + /// Progress notification. + void progressing(const QString& message); + private: /* diff --git a/geo/tcSrtmData.cpp b/geo/tcSrtmData.cpp index e3862bd..50c400f 100644 --- a/geo/tcSrtmData.cpp +++ b/geo/tcSrtmData.cpp @@ -35,13 +35,15 @@ */ /// Load SRTM data. -tcSrtmData::tcSrtmData(int lon, int lat, QFile& file) +tcSrtmData::tcSrtmData(int lon, int lat, QFile& file, QObject* progressObj, const char* progressMember) : m_lon(lon) , m_lat(lat) , m_lines(0) , m_samples(0) , m_data(0) { + connect(this, SIGNAL(progressing(const QString&)), progressObj, progressMember); + qint64 elements = file.size() / sizeof(uint16_t); double side = sqrt(elements); m_lines = m_samples = (int)side; @@ -51,8 +53,15 @@ tcSrtmData::tcSrtmData(int lon, int lat, QFile& file) QDataStream in(&file); in.setByteOrder(QDataStream::BigEndian); + int lastPercent = -1; for (int i = 0; i < m_lines; ++i) { + int percent = 20*i/(m_lines-1); + if (percent != lastPercent) + { + lastPercent = percent; + progressing(tr("Loading SRTM (%1,%2): %3%").arg(lon).arg(lat).arg(percent*5)); + } for (int j = 0; j < m_samples; ++j) { Q_ASSERT(!in.atEnd()); @@ -65,7 +74,10 @@ tcSrtmData::tcSrtmData(int lon, int lat, QFile& file) /// @todo Handle larger files! Q_ASSERT(in.atEnd()); + progressing(tr("Filling SRTM voids (%1,%2)").arg(lon).arg(lat)); fillVoidsBicubic(); + + progressing(tr("SRTM (%1,%2): Complete").arg(lon).arg(lat)); } /// Destructor. diff --git a/geo/tcSrtmData.h b/geo/tcSrtmData.h index 73ad266..37a7ec8 100644 --- a/geo/tcSrtmData.h +++ b/geo/tcSrtmData.h @@ -27,13 +27,18 @@ #include "tcGeo.h" +#include + #include class QFile; +class QString; /// Block of raw SRTM elevation data. -class tcSrtmData +class tcSrtmData : public QObject { + Q_OBJECT + public: /* @@ -45,7 +50,7 @@ class tcSrtmData * @param lat Latitude in degrees. * @param file File to read data from. */ - tcSrtmData(int lon, int lat, QFile& file); + tcSrtmData(int lon, int lat, QFile& file, QObject* progressObj, const char* progressMember); /// Destructor. virtual ~tcSrtmData(); @@ -94,6 +99,15 @@ class tcSrtmData /// Fill voids using bicubic interpolation. void fillVoidsBicubic(); + signals: + + /* + * Signals + */ + + /// Process notifier. + void progressing(const QString& message); + private: /* diff --git a/geo/tcSrtmModel.cpp b/geo/tcSrtmModel.cpp index 30d1c69..daba4d2 100644 --- a/geo/tcSrtmModel.cpp +++ b/geo/tcSrtmModel.cpp @@ -255,5 +255,9 @@ void tcSrtmModel::setDataSet(const QString& name) { delete m_cache; m_cache = new tcSrtmCache(name); + if (0 != m_cache) + { + connect(m_cache, SIGNAL(progressing(const QString&)), this, SIGNAL(progressing(const QString&))); + } emit dataSetChanged(); } diff --git a/geo/tcSrtmModel.h b/geo/tcSrtmModel.h index 05096b4..0db5df9 100644 --- a/geo/tcSrtmModel.h +++ b/geo/tcSrtmModel.h @@ -127,6 +127,9 @@ class tcSrtmModel : public QObject /// Emitted when the dataset is changed. void dataSetChanged(); + /// Progress notifier. + void progressing(const QString& progress); + private: /* diff --git a/tcMainWindow.cpp b/tcMainWindow.cpp index b63ce3c..4f4f21d 100644 --- a/tcMainWindow.cpp +++ b/tcMainWindow.cpp @@ -94,6 +94,10 @@ tcMainWindow::tcMainWindow() QStatusBar* statusBar = new QStatusBar(this); connect(m_viewport, SIGNAL(mouseGeoTextChanged(const QString&)), statusBar, SLOT(showMessage(const QString&))); + connect(m_globe->imagery()->channelManager(), SIGNAL(progressing(const QString&)), + statusBar, SLOT(showMessage(const QString&))); + connect(m_globe->dem(), SIGNAL(progressing(const QString&)), + statusBar, SLOT(showMessage(const QString&))); setStatusBar(statusBar); } @@ -127,10 +131,10 @@ tcMainWindow::tcMainWindow() connect(elevFlat, SIGNAL(pressed()), m_viewport, SLOT(setElevationFlat())); QRadioButton* elevRaw = new QRadioButton(tr("Raw SRTM Elevation Data"), dockerWidget); layout->addWidget(elevRaw); - elevRaw->setChecked(true); connect(elevRaw, SIGNAL(pressed()), m_viewport, SLOT(setElevationRaw())); QRadioButton* elevCorrected = new QRadioButton(tr("Corrected SRTM Elevation Data"), dockerWidget); layout->addWidget(elevCorrected); + elevCorrected->setChecked(true); connect(elevCorrected, SIGNAL(pressed()), m_viewport, SLOT(setElevationCorrected())); QSlider* elevCorrectionLevel = new QSlider(Qt::Horizontal, dockerWidget); layout->addWidget(elevCorrectionLevel); -- 2.11.4.GIT