Commit 109faf10 authored by schultezub's avatar schultezub

* 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 "tgt/assert.h"
#include "tgt/camera.h"
#include "tgt/quadric.h"
......@@ -6,7 +7,9 @@ namespace TUMVis {
const std::string TumVisPainter::loggerCat_ = "TUMVis.core.TumVisPainter";
TumVisPainter::TumVisPainter(tgt::GLCanvas* canvas)
: tgt::Painter(canvas) {
: tgt::Painter(canvas)
{
tgtAssert(getCanvas() != 0, "The given canvas must not be 0!");
}
void TumVisPainter::paint() {
......
......@@ -18,6 +18,8 @@ namespace TUMVis {
* 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!).
*
* \todo We definately want thread-safety here!
*
* \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.
*/
......
......@@ -23,7 +23,7 @@ namespace TUMVis {
* given AbstractData instance. So do not delete it once it has been assigned to a
* DataHandle (respectively DataContainer).
*
* \todo
* \todo implement locks/mutexes as soon as we have a convenient library for that.
*/
class DataHandle {
......@@ -48,6 +48,7 @@ namespace TUMVis {
*/
AbstractData* getData();
private:
/**
* Creates a new DataHandle for \a data and takes its ownership in terms of lifetime management.
......
......@@ -4,6 +4,7 @@
#include "tgt/texture.h"
#include "tgt/vector.h"
#include "core/datastructures/imagedata.h"
#include "core/tools/typetraits.h"
#include "core/tools/weaklytypedpointer.h"
namespace TUMVis {
......
......@@ -3,34 +3,22 @@
namespace TUMVis {
const std::string AbstractPipeline::loggerCat_ = "TUMVis.core.datastructures.AbstractPipeline";
AbstractPipeline::AbstractPipeline(tgt::GLCanvas* canvas /*= 0*/)
: _canvas(canvas)
AbstractPipeline::AbstractPipeline()
{
}
AbstractPipeline::~AbstractPipeline() {
}
void AbstractPipeline::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);
}
}
PropertyCollection& AbstractPipeline::getPropertyCollection() {
return _properties;
}
void AbstractPipeline::setCanvas(tgt::GLCanvas* canvas) {
if (_canvas != 0 && _canvas->getEventHandler() != 0) {
_canvas->getEventHandler()->removeListener(this);
}
_canvas = canvas;
if (_canvas->getEventHandler() != 0) {
_canvas->getEventHandler()->addListenerToFront(this);
}
void AbstractPipeline::init() {
// initialize all processors:
// for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) {
// (*it)->initGL();
// }
}
PropertyCollection& AbstractPipeline::getPropertyCollection() {
return _properties;
}
}
#ifndef ABSTRACTPIPELINE_H__
#define ABSTRACTPIPELINE_H__
#include "tgt/glcanvas.h"
#include "tgt/logmanager.h"
#include "tgt/event/eventlistener.h"
#include "core/datastructures/datacontainer.h"
#include "core/eventhandlers/abstracteventhandler.h"
#include "core/pipeline/abstractprocessor.h"
#include "core/properties/propertycollection.h"
#include <vector>
......@@ -16,12 +14,12 @@ namespace TUMVis {
* Abstract base class for TUMVis Pipelines.
*
*/
class AbstractPipeline : public tgt::EventListener {
class AbstractPipeline {
public:
/**
* Creates a AbstractPipeline.
*/
AbstractPipeline(tgt::GLCanvas* canvas = 0);
AbstractPipeline();
/**
* Virtual Destructor
......@@ -30,22 +28,16 @@ namespace TUMVis {
/**
* 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
* Initializes the OpenGL context of the pipeline and its processors.
*
* \note When overwriting this method, make sure to call the base class version first.
*/
virtual void onEvent(tgt::Event* e);
virtual void init();
/**
* Sets the target canvas for rendering.
* \param canvas Target canvas for rendering
*/
void setCanvas(tgt::GLCanvas* canvas);
* Execute this pipeline.
**/
virtual void execute() = 0;
/**
* Returns the PropertyCollection of this processor.
......@@ -55,9 +47,8 @@ namespace TUMVis {
protected:
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
static const std::string loggerCat_;
......
......@@ -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 {
return _invalidationLevel;
}
void AbstractProcessor::applyInvalidationLevel(InvalidationLevel::NamedLevels nl) {
_invalidationLevel.setLevel(nl);
}
void AbstractProcessor::onNotify(const PropertyObserverArgs& poa) {
_invalidationLevel.setLevel(poa._invalidationLevel);
void AbstractProcessor::applyInvalidationLevel(InvalidationLevel il) {
_invalidationLevel.setLevel(il);
// If processor is no longer valid, notify observers
if (! _invalidationLevel.isValid()) {
......@@ -38,7 +26,12 @@ namespace TUMVis {
}
}
void AbstractProcessor::onNotify(const PropertyObserverArgs& poa) {
applyInvalidationLevel(poa._invalidationLevel);
}
PropertyCollection& AbstractProcessor::getPropertyCollection() {
return _properties;
}
}
......@@ -33,10 +33,28 @@ namespace TUMVis {
/**
* 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
*/
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:
/**
......@@ -52,23 +70,9 @@ namespace TUMVis {
/**
* Execute this processor.
* \param data DataContainer to work on.
**/
virtual void process() = 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;
virtual void process(DataContainer& data) = 0;
/**
* Returns the invalidation level of this processor.
......@@ -78,7 +82,7 @@ namespace TUMVis {
/**
* Returns the PropertyCollection of this processor.
* \return _properties
* \return _properties
*/
PropertyCollection& getPropertyCollection();
......@@ -88,9 +92,8 @@ namespace TUMVis {
* If \a nl is one of the INVALID_X state, the processor's corresponding flag will be set.
* \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.
* \sa GenericObserver::onNotify, AbstractProperty
......@@ -100,7 +103,6 @@ namespace TUMVis {
protected:
DataContainer _dataContainer; ///< DataContainer containing local working set of data for this Processor
InvalidationLevel _invalidationLevel; ///< current invalidation level 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 {
* Abstract base class for TUMVis Property.
*
* \todo Add PropertyWidgets, add clone()?
* Think about a reasonable locking mechanism and implement that
*/
class AbstractProperty : public GenericObservable<PropertyObserverArgs> {
public:
......
......@@ -27,7 +27,7 @@ namespace TUMVis {
INT32, ///< signed 32 bit integer
FLOAT, ///< float
UINT64, ///< unsigned 64 bit integer
INT64, ///< signed 64 bit integer q
INT64, ///< signed 64 bit integer
DOUBLE ///< double
};
......
......@@ -17,20 +17,24 @@ namespace TUMVis {
MhdImageReader::MhdImageReader()
: AbstractProcessor()
, _url("url", "Image URL", "")
, _targetImageID("targetImageName", "Target Image ID", "MhdImageReader.output")
{
_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() {
}
void MhdImageReader::process() {
void MhdImageReader::process(DataContainer& data) {
TextFileParser tfp(_url.getValue(), true, "=");
tfp.parse<TextFileParser::ItemSeparatorLines>();
// init optional parameters with sane default values
std::string url;
size_t dimensionality;
tgt::svec3 size;
......@@ -119,7 +123,7 @@ namespace TUMVis {
// all parsing done - lets create the image:
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) {
LERROR("Error while parsing MHD header: " << e.what());
......
......@@ -8,7 +8,7 @@
namespace TUMVis {
/**
*
* Reads a MHD image file into the pipeline.
*
* \note Full format specification at http://www.itk.org/Wiki/MetaIO/Documentation
*/
......@@ -25,13 +25,16 @@ namespace TUMVis {
virtual ~MhdImageReader();
virtual void process();
/**
* Reads the MHD file into an ImageDataDisk representation
* \param data DataContainer to work on
*/
virtual void process(DataContainer& data);
private:
void parseHeader();
// TODO make this a property as soon as the property system exists
GenericProperty<std::string> _url;
GenericProperty<std::string> _url; ///< URL for file to read
GenericProperty<std::string> _targetImageID; ///< image ID for read image
static const std::string loggerCat_;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment