Commit 109faf10 authored by schultezub's avatar schultezub
Browse files

* put class diagram under version control

 * Processors no longer have their own DataContainer, instead the DataContainer to work on is passed during process()
 * introduced VisualizationPipeline

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@180 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 5e424b90
#include "tumvispainter.h" #include "tumvispainter.h"
#include "tgt/assert.h"
#include "tgt/camera.h" #include "tgt/camera.h"
#include "tgt/quadric.h" #include "tgt/quadric.h"
...@@ -6,7 +7,9 @@ namespace TUMVis { ...@@ -6,7 +7,9 @@ namespace TUMVis {
const std::string TumVisPainter::loggerCat_ = "TUMVis.core.TumVisPainter"; const std::string TumVisPainter::loggerCat_ = "TUMVis.core.TumVisPainter";
TumVisPainter::TumVisPainter(tgt::GLCanvas* canvas) TumVisPainter::TumVisPainter(tgt::GLCanvas* canvas)
: tgt::Painter(canvas) { : tgt::Painter(canvas)
{
tgtAssert(getCanvas() != 0, "The given canvas must not be 0!");
} }
void TumVisPainter::paint() { void TumVisPainter::paint() {
......
...@@ -18,6 +18,8 @@ namespace TUMVis { ...@@ -18,6 +18,8 @@ namespace TUMVis {
* also ensures (hopefully) that nobody can do messy things, such as adding the same AbstractData instance * also ensures (hopefully) that nobody can do messy things, such as adding the same AbstractData instance
* twice to a DataContainer (which would really mess up the lifetime management!). * twice to a DataContainer (which would really mess up the lifetime management!).
* *
* \todo We definately want thread-safety here!
*
* \todo If the original data changes, the other objects accessing that very DataHandle might want to * \todo If the original data changes, the other objects accessing that very DataHandle might want to
* get notified of the change. Hence, some observer pattern might be useful. * get notified of the change. Hence, some observer pattern might be useful.
*/ */
......
...@@ -23,7 +23,7 @@ namespace TUMVis { ...@@ -23,7 +23,7 @@ namespace TUMVis {
* given AbstractData instance. So do not delete it once it has been assigned to a * given AbstractData instance. So do not delete it once it has been assigned to a
* DataHandle (respectively DataContainer). * DataHandle (respectively DataContainer).
* *
* \todo * \todo implement locks/mutexes as soon as we have a convenient library for that.
*/ */
class DataHandle { class DataHandle {
...@@ -48,6 +48,7 @@ namespace TUMVis { ...@@ -48,6 +48,7 @@ namespace TUMVis {
*/ */
AbstractData* getData(); AbstractData* getData();
private: private:
/** /**
* Creates a new DataHandle for \a data and takes its ownership in terms of lifetime management. * Creates a new DataHandle for \a data and takes its ownership in terms of lifetime management.
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "tgt/texture.h" #include "tgt/texture.h"
#include "tgt/vector.h" #include "tgt/vector.h"
#include "core/datastructures/imagedata.h" #include "core/datastructures/imagedata.h"
#include "core/tools/typetraits.h"
#include "core/tools/weaklytypedpointer.h" #include "core/tools/weaklytypedpointer.h"
namespace TUMVis { namespace TUMVis {
......
...@@ -3,34 +3,22 @@ ...@@ -3,34 +3,22 @@
namespace TUMVis { namespace TUMVis {
const std::string AbstractPipeline::loggerCat_ = "TUMVis.core.datastructures.AbstractPipeline"; const std::string AbstractPipeline::loggerCat_ = "TUMVis.core.datastructures.AbstractPipeline";
AbstractPipeline::AbstractPipeline(tgt::GLCanvas* canvas /*= 0*/) AbstractPipeline::AbstractPipeline()
: _canvas(canvas)
{ {
} }
AbstractPipeline::~AbstractPipeline() { AbstractPipeline::~AbstractPipeline() {
} }
void AbstractPipeline::onEvent(tgt::Event* e) { PropertyCollection& AbstractPipeline::getPropertyCollection() {
// cycle through event handlers, ask each one if it handles the event and if so, execute it. return _properties;
for (std::vector<AbstractEventHandler*>::iterator it = _eventHandlers.begin(); it != _eventHandlers.end() && !e->isAccepted(); ++it) {
if ((*it)->accept(e)) {
(*it)->execute(e);
}
}
} }
void AbstractPipeline::setCanvas(tgt::GLCanvas* canvas) { void AbstractPipeline::init() {
if (_canvas != 0 && _canvas->getEventHandler() != 0) { // initialize all processors:
_canvas->getEventHandler()->removeListener(this); // for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) {
} // (*it)->initGL();
_canvas = canvas; // }
if (_canvas->getEventHandler() != 0) {
_canvas->getEventHandler()->addListenerToFront(this);
}
} }
PropertyCollection& AbstractPipeline::getPropertyCollection() {
return _properties;
}
} }
#ifndef ABSTRACTPIPELINE_H__ #ifndef ABSTRACTPIPELINE_H__
#define ABSTRACTPIPELINE_H__ #define ABSTRACTPIPELINE_H__
#include "tgt/glcanvas.h"
#include "tgt/logmanager.h" #include "tgt/logmanager.h"
#include "tgt/event/eventlistener.h"
#include "core/datastructures/datacontainer.h" #include "core/datastructures/datacontainer.h"
#include "core/eventhandlers/abstracteventhandler.h" #include "core/pipeline/abstractprocessor.h"
#include "core/properties/propertycollection.h" #include "core/properties/propertycollection.h"
#include <vector> #include <vector>
...@@ -16,12 +14,12 @@ namespace TUMVis { ...@@ -16,12 +14,12 @@ namespace TUMVis {
* Abstract base class for TUMVis Pipelines. * Abstract base class for TUMVis Pipelines.
* *
*/ */
class AbstractPipeline : public tgt::EventListener { class AbstractPipeline {
public: public:
/** /**
* Creates a AbstractPipeline. * Creates a AbstractPipeline.
*/ */
AbstractPipeline(tgt::GLCanvas* canvas = 0); AbstractPipeline();
/** /**
* Virtual Destructor * Virtual Destructor
...@@ -30,22 +28,16 @@ namespace TUMVis { ...@@ -30,22 +28,16 @@ namespace TUMVis {
/** /**
* Execute this pipeline. * Initializes the OpenGL context of the pipeline and its processors.
**/ *
virtual void execute() = 0; * \note When overwriting this method, make sure to call the base class version first.
/**
* Performs the event handling for the assigned canvas.
* Default behaviour is to execute all assigned EventHandlers, may be overwritten by subclasses.
* \param e event parameters
*/ */
virtual void onEvent(tgt::Event* e); virtual void init();
/** /**
* Sets the target canvas for rendering. * Execute this pipeline.
* \param canvas Target canvas for rendering **/
*/ virtual void execute() = 0;
void setCanvas(tgt::GLCanvas* canvas);
/** /**
* Returns the PropertyCollection of this processor. * Returns the PropertyCollection of this processor.
...@@ -55,9 +47,8 @@ namespace TUMVis { ...@@ -55,9 +47,8 @@ namespace TUMVis {
protected: protected:
DataContainer _data; ///< DataContainer containing local working set of data for this Pipeline DataContainer _data; ///< DataContainer containing local working set of data for this Pipeline
tgt::GLCanvas* _canvas; ///< Target canvas for rendering
std::vector<AbstractEventHandler*> _eventHandlers; ///< List of registered event handlers for the pipeline std::vector<AbstractProcessor*> _processors; ///< List of all processors of this pipeline
PropertyCollection _properties; ///< PropertyCollection of this pipeline, put in here all properties you want to be publicly accessible PropertyCollection _properties; ///< PropertyCollection of this pipeline, put in here all properties you want to be publicly accessible
static const std::string loggerCat_; static const std::string loggerCat_;
......
...@@ -13,24 +13,12 @@ namespace TUMVis { ...@@ -13,24 +13,12 @@ namespace TUMVis {
} }
void AbstractProcessor::addDataHandle(const std::string& name, const DataHandle* dh) {
_dataContainer.addDataHandle(name, dh);
}
const DataContainer& AbstractProcessor::getDataContainer() const {
return _dataContainer;
}
const InvalidationLevel& AbstractProcessor::getInvalidationLevel() const { const InvalidationLevel& AbstractProcessor::getInvalidationLevel() const {
return _invalidationLevel; return _invalidationLevel;
} }
void AbstractProcessor::applyInvalidationLevel(InvalidationLevel::NamedLevels nl) { void AbstractProcessor::applyInvalidationLevel(InvalidationLevel il) {
_invalidationLevel.setLevel(nl); _invalidationLevel.setLevel(il);
}
void AbstractProcessor::onNotify(const PropertyObserverArgs& poa) {
_invalidationLevel.setLevel(poa._invalidationLevel);
// If processor is no longer valid, notify observers // If processor is no longer valid, notify observers
if (! _invalidationLevel.isValid()) { if (! _invalidationLevel.isValid()) {
...@@ -38,7 +26,12 @@ namespace TUMVis { ...@@ -38,7 +26,12 @@ namespace TUMVis {
} }
} }
void AbstractProcessor::onNotify(const PropertyObserverArgs& poa) {
applyInvalidationLevel(poa._invalidationLevel);
}
PropertyCollection& AbstractProcessor::getPropertyCollection() { PropertyCollection& AbstractProcessor::getPropertyCollection() {
return _properties; return _properties;
} }
} }
...@@ -33,10 +33,28 @@ namespace TUMVis { ...@@ -33,10 +33,28 @@ namespace TUMVis {
/** /**
* Abstract base class for TUMVis Processors. * Abstract base class for TUMVis Processors.
* A processor implements a specific task, which it performs on the DataCollection passed
* during process(). Properties provide a transparent layer for adjusting the processor's
* behaviour.
* Once a processor has finished it sets it should set its invalidation level to valid. As
* soon as one of its properties changes, the processor will be notified and possibliy
* change its invalidation level. Observing pipelines will be notified of this and can
* and have to decide which part of the pipeline has to be re-evaluated wrt. the processor's
* invalidation level.
* *
* \sa AbstractPipeline * \sa AbstractPipeline
*/ */
class AbstractProcessor : GenericObserver<PropertyObserverArgs>, public GenericObservable<ProcessorObserverArgs> { class AbstractProcessor : GenericObserver<PropertyObserverArgs>, public GenericObservable<ProcessorObserverArgs> {
/**
* We have to find a trade-off:
* On the one hand, we want to follow the information-hiding concept and keep the processor's
* properties private. On the other hand pipelines will usually want direct access to them
* (e.g. in order to setup data IDs or property sharing) and the properties in the PropertyCollection
* are not strongly typed. Hence, we declare AbstractPipeline as our friend.
*/
friend class AbstractPipeline;
public: public:
/** /**
...@@ -52,23 +70,9 @@ namespace TUMVis { ...@@ -52,23 +70,9 @@ namespace TUMVis {
/** /**
* Execute this processor. * Execute this processor.
* \param data DataContainer to work on.
**/ **/
virtual void process() = 0; virtual void process(DataContainer& data) = 0;
/**
* Adds the given DataHandle \a data, accessible by the key \name, to this DataContainer.
* Already existing DataHandles with the same key will be removed from this DataContainer.
*
* \param name Key for accessing the DataHandle within this DataContainer
* \param data DataHandle to add.
**/
virtual void addDataHandle(const std::string& name, const DataHandle* dh);
/**
* Returns the local DataContainer of this Processor.
* \return _dataContainer
**/
const DataContainer& getDataContainer() const;
/** /**
* Returns the invalidation level of this processor. * Returns the invalidation level of this processor.
...@@ -88,8 +92,7 @@ namespace TUMVis { ...@@ -88,8 +92,7 @@ namespace TUMVis {
* If \a nl is one of the INVALID_X state, the processor's corresponding flag will be set. * If \a nl is one of the INVALID_X state, the processor's corresponding flag will be set.
* \param nl Invalidation level to apply. * \param nl Invalidation level to apply.
*/ */
void applyInvalidationLevel(InvalidationLevel::NamedLevels nl); void applyInvalidationLevel(InvalidationLevel il);
/** /**
* Gets called when one of the observed properties changed notifies its observers. * Gets called when one of the observed properties changed notifies its observers.
...@@ -100,7 +103,6 @@ namespace TUMVis { ...@@ -100,7 +103,6 @@ namespace TUMVis {
protected: protected:
DataContainer _dataContainer; ///< DataContainer containing local working set of data for this Processor
InvalidationLevel _invalidationLevel; ///< current invalidation level of this processor InvalidationLevel _invalidationLevel; ///< current invalidation level of this processor
PropertyCollection _properties; ///< PropertyCollection of this processor PropertyCollection _properties; ///< PropertyCollection of this processor
......
#include "visualizationpipeline.h"
namespace TUMVis {
const std::string VisualizationPipeline::loggerCat_ = "TUMVis.core.datastructures.VisualizationPipeline";
VisualizationPipeline::VisualizationPipeline(tgt::GLCanvas* canvas /*= 0*/)
: _canvas(canvas)
{
}
VisualizationPipeline::~VisualizationPipeline() {
}
void VisualizationPipeline::onEvent(tgt::Event* e) {
// cycle through event handlers, ask each one if it handles the event and if so, execute it.
for (std::vector<AbstractEventHandler*>::iterator it = _eventHandlers.begin(); it != _eventHandlers.end() && !e->isAccepted(); ++it) {
if ((*it)->accept(e)) {
(*it)->execute(e);
}
}
}
void VisualizationPipeline::setCanvas(tgt::GLCanvas* canvas) {
if (_canvas != 0 && _canvas->getEventHandler() != 0) {
_canvas->getEventHandler()->removeListener(this);
}
_canvas = canvas;
if (_canvas->getEventHandler() != 0) {
_canvas->getEventHandler()->addListenerToFront(this);
}
}
PropertyCollection& VisualizationPipeline::getPropertyCollection() {
return _properties;
}
void VisualizationPipeline::init() {
AbstractPipeline::init();
// initialize all processors:
// for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) {
// (*it)->initGL();
// }
}
void VisualizationPipeline::paint() {
// TODO: implement - is there a generic way to initiate the painting in the subclasses?
}
void VisualizationPipeline::sizeChanged(const tgt::ivec2& size) {
// nothing to change if nothing changes
if (size != _canvasSize) {
_canvasSize = size;
}
// TODO: initiate pipeline evaluation, is a simple execute() what we want?
execute();
}
}
#ifndef VISUALIZATIONPIPELINE_H__
#define VISUALIZATIONPIPELINE_H__
#include "tgt/glcanvas.h"
#include "tgt/painter.h"
#include "tgt/event/eventlistener.h"
#include "core/eventhandlers/abstracteventhandler.h"
#include "core/pipeline/abstractpipeline.h"
#include <vector>
namespace TUMVis {
/**
* Abstract base class for TUMVis Pipelines.
*
*/
class VisualizationPipeline : public AbstractPipeline, public tgt::EventListener, public tgt::Painter {
public:
/**
* Creates a VisualizationPipeline.
*/
VisualizationPipeline(tgt::GLCanvas* canvas = 0);
/**
* Virtual Destructor
**/
virtual ~VisualizationPipeline();
/**
* Initializes the OpenGL context of the pipeline and its processors.
* \todo merge with init() ?
* \note When overwriting this method, make sure to call the base class version first.
*/
virtual void init();
/**
* Execute this pipeline.
**/
virtual void execute() = 0;
/**
* Performs the event handling for the assigned canvas.
* Default behaviour is to execute all assigned EventHandlers, may be overwritten by subclasses.
* \param e event parameters
*/
virtual void onEvent(tgt::Event* e);
/**
* Acquires the OpenGL context, and executes the pipeline
*/
virtual void paint();
/**
* Is called when the viewport dimensions change, notifies the pipeline of that.
* \param size New viewport dimensions
*/
virtual void sizeChanged(const tgt::ivec2& size);
/**
* Sets the target canvas for rendering.
* \param canvas Target canvas for rendering
*/
void setCanvas(tgt::GLCanvas* canvas);
/**
* Returns the PropertyCollection of this processor.
* \return _properties
*/
PropertyCollection& getPropertyCollection();
protected:
DataContainer _data; ///< DataContainer containing local working set of data for this Pipeline
tgt::GLCanvas* _canvas; ///< Target canvas for rendering
tgt::ivec2 _canvasSize; ///< Viewport size of target canvas
std::vector<AbstractEventHandler*> _eventHandlers; ///< List of registered event handlers for the pipeline
std::vector<AbstractProcessor*> _processors; ///< List of all processors of this pipeline
PropertyCollection _properties; ///< PropertyCollection of this pipeline, put in here all properties you want to be publicly accessible
static const std::string loggerCat_;
};
}
#endif // VISUALIZATIONPIPELINE_H__
...@@ -36,6 +36,7 @@ namespace TUMVis { ...@@ -36,6 +36,7 @@ namespace TUMVis {
* Abstract base class for TUMVis Property. * Abstract base class for TUMVis Property.
* *
* \todo Add PropertyWidgets, add clone()? * \todo Add PropertyWidgets, add clone()?
* Think about a reasonable locking mechanism and implement that
*/ */
class AbstractProperty : public GenericObservable<PropertyObserverArgs> { class AbstractProperty : public GenericObservable<PropertyObserverArgs> {
public: public:
......
...@@ -27,7 +27,7 @@ namespace TUMVis { ...@@ -27,7 +27,7 @@ namespace TUMVis {
INT32, ///< signed 32 bit integer INT32, ///< signed 32 bit integer
FLOAT, ///< float FLOAT, ///< float
UINT64, ///< unsigned 64 bit integer UINT64, ///< unsigned 64 bit integer
INT64, ///< signed 64 bit integer q INT64, ///< signed 64 bit integer
DOUBLE ///< double DOUBLE ///< double
}; };
......
...@@ -17,20 +17,24 @@ namespace TUMVis { ...@@ -17,20 +17,24 @@ namespace TUMVis {
MhdImageReader::MhdImageReader() MhdImageReader::MhdImageReader()
: AbstractProcessor() : AbstractProcessor()
, _url("url", "Image URL", "") , _url("url", "Image URL", "")
, _targetImageID("targetImageName", "Target Image ID", "MhdImageReader.output")
{ {
_properties.addProperty(&_url); _properties.addProperty(&_url);
_properties.addProperty(&_targetImageID);
ImageDataRAMTraits<float, 2>::ImageType* img = new ImageDataRAMTraits<float, 2>::ImageType(2, tgt::svec3(2, 2, 1), 0); // just testing some type traits...
//ImageDataRAMTraits<float, 2>::ImageType* img = new ImageDataRAMTraits<float, 2>::ImageType(2, tgt::svec3(2, 2, 1), 0);
} }
MhdImageReader::~MhdImageReader() { MhdImageReader::~MhdImageReader() {
} }
void MhdImageReader::process() { void MhdImageReader::process(DataContainer& data) {
TextFileParser tfp(_url.getValue(), true, "="); TextFileParser tfp(_url.getValue(), true, "=");
tfp.parse<TextFileParser::ItemSeparatorLines>(); tfp.parse<TextFileParser::ItemSeparatorLines>();
// init optional parameters with sane default values
std::string url; std::string url;
size_t dimensionality; size_t dimensionality;
tgt::svec3 size; tgt::svec3 size;
...@@ -119,7 +123,7 @@ namespace TUMVis { ...@@ -119,7 +123,7 @@ namespace TUMVis {
// all parsing done - lets create the image: // all parsing done - lets create the image:
ImageDataDisk* image = new ImageDataDisk(url, dimensionality, size, pt, offset, e); ImageDataDisk* image = new ImageDataDisk(url, dimensionality, size, pt, offset, e);
_dataContainer.addData("output.image.read", image); data.addData(_targetImageID.getValue(), image);
} }
catch (tgt::Exception& e) { catch (tgt::Exception& e) {
LERROR("Error while parsing MHD header: " << e.what()); LERROR("Error while parsing MHD header: " << e.what());
......