The expiration time for new job artifacts in CI/CD pipelines is now 30 days (GitLab default). Previously generated artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

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.
...@@ -78,7 +82,7 @@ namespace TUMVis { ...@@ -78,7 +82,7 @@ namespace TUMVis {
/** /**
* Returns the PropertyCollection of this processor. * Returns the PropertyCollection of this processor.
* \return _properties * \return _properties
*/ */
PropertyCollection& getPropertyCollection(); PropertyCollection& getPropertyCollection();
...@@ -88,9 +92,8 @@ namespace TUMVis { ...@@ -88,9 +92,8 @@ 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.
* \sa GenericObserver::onNotify, AbstractProperty * \sa GenericObserver::onNotify, AbstractProperty
...@@ -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,