From: Leonardo Florez-Valencia Date: Thu, 10 Dec 2015 00:22:50 +0000 (-0500) Subject: Pipeline editor added. X-Git-Tag: v0.1~287 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=950ea6d252c9a5bc5be29d413497fe0ef69e6703;p=cpPlugins.git Pipeline editor added. --- diff --git a/appli/CMakeLists.txt b/appli/CMakeLists.txt index 2568ba0..6e0414c 100644 --- a/appli/CMakeLists.txt +++ b/appli/CMakeLists.txt @@ -6,6 +6,7 @@ IF(BUILD_EXAMPLES) SUBDIRS( examples ImageMPR + cpPipelineEditor ) ENDIF(BUILD_EXAMPLES) diff --git a/appli/cpPipelineEditor/CMakeLists.txt b/appli/cpPipelineEditor/CMakeLists.txt new file mode 100644 index 0000000..5ecebcd --- /dev/null +++ b/appli/cpPipelineEditor/CMakeLists.txt @@ -0,0 +1,72 @@ +IF(USE_QT4) + SET(App_NAME "cpPipelineEditor") + + ## ==================================================== + ## = Source code, user interafaces and resources here = + ## ==================================================== + + SET(App_SOURCE_DIR "${PROJECT_SOURCE_DIR}/appli/${App_NAME}") + SET(App_BINARY_DIR "${PROJECT_BINARY_DIR}/appli/${App_NAME}") + + SET( + App_QT_SOURCES + Edge.cxx + GraphWidget.cxx + Node.cxx + cpPipelineEditor.cxx + ) + SET( + App_SOURCES + main.cxx + ) + SET( + App_QT_HEADERS + Edge.h + GraphWidget.h + Node.h + cpPipelineEditor.h + ) + SET( + App_HEADERS + ) + FILE(GLOB App_QT_UI "${App_SOURCE_DIR}/*.ui") + FILE(GLOB App_QT_RES "${App_SOURCE_DIR}/*.qrc") + + ## ===================== + ## = Compilation rules = + ## ===================== + INCLUDE_DIRECTORIES( + ${App_SOURCE_DIR} + ${App_BINARY_DIR} + ) + + QT4_WRAP_UI(App_QT_UI_Headers ${App_QT_UI}) + QT4_WRAP_CPP(App_QT_HEADERS_MOC_SOURCES ${App_QT_HEADERS}) + QT4_ADD_RESOURCES(App_QT_RES_SOURCES ${App_QT_RES}) + + SET(GUI_TYPE "") + IF(WIN32) + SET(GUI_TYPE WIN32) + ENDIF(WIN32) + IF(APPLE) + SET(GUI_TYPE MACOSX_BUNDLE) + ENDIF(APPLE) + + ADD_EXECUTABLE( + ${App_NAME} + ${GUI_TYPE} + ${App_QT_UI_Headers} + ${App_SOURCES} + ${App_QT_SOURCES} + ${App_QT_HEADERS_MOC_SOURCES} + ${App_QT_RES_SOURCES} + ) + TARGET_LINK_LIBRARIES( + ${App_NAME} + ${QT_LIBRARIES} + cpExtensions + cpPlugins_Interface + ) +ENDIF(USE_QT4) + +## eof - $RCSfile$ diff --git a/appli/cpPipelineEditor/Edge.cxx b/appli/cpPipelineEditor/Edge.cxx new file mode 100644 index 0000000..1442a61 --- /dev/null +++ b/appli/cpPipelineEditor/Edge.cxx @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "Edge.h" +#include "Node.h" + +#include + +static const double Pi = 3.14159265358979323846264338327950288419717; +static double TwoPi = 2.0 * Pi; + +Edge::Edge(Node *sourceNode, Node *destNode) + : arrowSize(10) +{ + setAcceptedMouseButtons(0); + source = sourceNode; + dest = destNode; + source->addEdge(this); + dest->addEdge(this); + this->setToolTip( "Edge!!!" ); + adjust(); +} + +Node *Edge::sourceNode() const +{ + return source; +} + +Node *Edge::destNode() const +{ + return dest; +} + +void Edge::adjust() +{ + if (!source || !dest) + return; + + QLineF line(mapFromItem(source, 0, 0), mapFromItem(dest, 0, 0)); + qreal length = line.length(); + + prepareGeometryChange(); + + if (length > qreal(20.)) { + QPointF edgeOffset((line.dx() * 10) / length, (line.dy() * 10) / length); + sourcePoint = line.p1() + edgeOffset; + destPoint = line.p2() - edgeOffset; + } else { + sourcePoint = destPoint = line.p1(); + } +} + +QRectF Edge::boundingRect() const +{ + if (!source || !dest) + return QRectF(); + + qreal penWidth = 1; + qreal extra = (penWidth + arrowSize) / 2.0; + + return QRectF(sourcePoint, QSizeF(destPoint.x() - sourcePoint.x(), + destPoint.y() - sourcePoint.y())) + .normalized() + .adjusted(-extra, -extra, extra, extra); +} + +void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + if (!source || !dest) + return; + + QLineF line(sourcePoint, destPoint); + if (qFuzzyCompare(line.length(), qreal(0.))) + return; + + // Draw the line itself + painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + painter->drawLine(line); + + // Draw the arrows + double angle = ::acos(line.dx() / line.length()); + if (line.dy() >= 0) + angle = TwoPi - angle; + + QPointF destArrowP1 = destPoint + QPointF( + sin(angle - Pi / 3) * arrowSize, + cos(angle - Pi / 3) * arrowSize + ); + QPointF destArrowP2 = destPoint + QPointF( + sin(angle - Pi + Pi / 3) * arrowSize, + cos(angle - Pi + Pi / 3) * arrowSize + ); + QPointF center = sourcePoint + destPoint; + center /= 2; + + painter->setBrush(Qt::black); + painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2); + painter->drawText( center, "Edge!!!" ); +} + +// eof - $RCSfile$ diff --git a/appli/cpPipelineEditor/Edge.h b/appli/cpPipelineEditor/Edge.h new file mode 100644 index 0000000..49bf282 --- /dev/null +++ b/appli/cpPipelineEditor/Edge.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EDGE_H +#define EDGE_H + +#include + +class Node; + +class Edge : public QGraphicsItem +{ +public: + Edge(Node *sourceNode, Node *destNode); + + Node *sourceNode() const; + Node *destNode() const; + + void adjust(); + + enum { Type = UserType + 2 }; + int type() const { return Type; } + +protected: + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + +private: + Node *source, *dest; + + QPointF sourcePoint; + QPointF destPoint; + qreal arrowSize; +}; + +#endif diff --git a/appli/cpPipelineEditor/GraphWidget.cxx b/appli/cpPipelineEditor/GraphWidget.cxx new file mode 100644 index 0000000..2eb9553 --- /dev/null +++ b/appli/cpPipelineEditor/GraphWidget.cxx @@ -0,0 +1,316 @@ +/**************************************************************************** + ** + ** Copyright (C) 2015 The Qt Company Ltd. + ** Contact: http://www.qt.io/licensing/ + ** + ** This file is part of the examples of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of The Qt Company Ltd nor the names of its + ** contributors may be used to endorse or promote products derived + ** from this software without specific prior written permission. + ** + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#include "GraphWidget.h" +#include "Edge.h" +#include "Node.h" + +#include + +#include + +#include + +GraphWidget::GraphWidget( QWidget* parent ) + : QGraphicsView( parent ), + timerId( 0 ), + m_Workspace( NULL ) +{ + QGraphicsScene* scene = new QGraphicsScene( this ); + scene->setItemIndexMethod( QGraphicsScene::NoIndex ); + // TODO: scene->setSceneRect( -200, -200, 400, 400 ); + this->setScene( scene ); + /* TODO + this->setCacheMode(CacheBackground); + this->setViewportUpdateMode(BoundingRectViewportUpdate); + this->setRenderHint(QPainter::Antialiasing); + this->setTransformationAnchor(AnchorUnderMouse); + this->scale(qreal(0.8), qreal(0.8)); + this->setMinimumSize(400, 400); + this->setWindowTitle( tr("Elastic Nodes") ); + */ + + /* + Node *node1 = new Node(this); + Node *node2 = new Node(this); + Node *node3 = new Node(this); + Node *node4 = new Node(this); + centerNode = new Node(this); + Node *node6 = new Node(this); + Node *node7 = new Node(this); + Node *node8 = new Node(this); + Node *node9 = new Node(this); + scene->addItem(node1); + scene->addItem(node2); + scene->addItem(node3); + scene->addItem(node4); + scene->addItem(centerNode); + scene->addItem(node6); + scene->addItem(node7); + scene->addItem(node8); + scene->addItem(node9); + scene->addItem(new Edge(node1, node2)); + scene->addItem(new Edge(node2, node3)); + scene->addItem(new Edge(node2, centerNode)); + scene->addItem(new Edge(node3, node6)); + scene->addItem(new Edge(node4, node1)); + scene->addItem(new Edge(node4, centerNode)); + scene->addItem(new Edge(centerNode, node6)); + scene->addItem(new Edge(centerNode, node8)); + scene->addItem(new Edge(node6, node9)); + scene->addItem(new Edge(node7, node4)); + scene->addItem(new Edge(node8, node7)); + scene->addItem(new Edge(node9, node8)); + + node1->setPos(-50, -50); + node2->setPos(0, -50); + node3->setPos(50, -50); + node4->setPos(-50, 0); + centerNode->setPos(0, 0); + node6->setPos(50, 0); + node7->setPos(-50, 50); + node8->setPos(0, 50); + node9->setPos(50, 50); + */ +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface::Workspace* GraphWidget:: +workspace( ) +{ + return( this->m_Workspace ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Interface::Workspace* GraphWidget:: +workspace( ) const +{ + return( this->m_Workspace ); +} + +// ------------------------------------------------------------------------- +void GraphWidget:: +setWorkspace( cpPlugins::Interface::Workspace* ws ) +{ + if( this->m_Workspace == ws ) + return; + this->m_Workspace = ws; + QGraphicsScene* scene = this->scene( ); + + // Create graph + this->m_Graph = TGraph::New( ); + + // Add vertices + auto vIt = this->m_Workspace->GetGraph( )->BeginVertices( ); + auto vIt_end = this->m_Workspace->GetGraph( )->EndVertices( ); + for( ; vIt != vIt_end; ++vIt ) + { + std::string label = vIt->second->GetName( ) + std::string( "\n" ); + label += vIt->second->GetClassName( ); + + Node* node = new Node( this, label ); + this->m_Graph->InsertVertex( vIt->first, node ); + scene->addItem( node ); + + } // rof + + // Add edges + auto rIt = this->m_Workspace->GetGraph( )->BeginEdgesRows( ); + auto rIt_end = this->m_Workspace->GetGraph( )->EndEdgesRows( ); + for( ; rIt != rIt_end; ++rIt ) + { + Node* a = this->m_Graph->GetVertex( rIt->first ); + if( a == NULL ) + continue; + auto cIt = rIt->second.begin( ); + for( ; cIt != rIt->second.end( ); ++cIt ) + { + Node* b = this->m_Graph->GetVertex( cIt->first ); + if( b == NULL ) + continue; + Edge* e = new Edge( a, b ); + this->m_Graph->AddConnection( rIt->first, cIt->first, e ); + scene->addItem( e ); + + } // rof + + } // rof +} + +// ------------------------------------------------------------------------- +void GraphWidget:: +draw( ) +{ + if( this->m_Workspace == NULL ) + return; +} + +// ------------------------------------------------------------------------- +void GraphWidget::itemMoved() +{ + if (!timerId) + timerId = startTimer(1000 / 25); +} + +void GraphWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Up: + centerNode->moveBy(0, -20); + break; + case Qt::Key_Down: + centerNode->moveBy(0, 20); + break; + case Qt::Key_Left: + centerNode->moveBy(-20, 0); + break; + case Qt::Key_Right: + centerNode->moveBy(20, 0); + break; + case Qt::Key_Plus: + zoomIn(); + break; + case Qt::Key_Minus: + zoomOut(); + break; + case Qt::Key_Space: + case Qt::Key_Enter: + shuffle(); + break; + default: + QGraphicsView::keyPressEvent(event); + } +} + +void GraphWidget::timerEvent(QTimerEvent *event) +{ + Q_UNUSED(event); + + QList nodes; + foreach (QGraphicsItem *item, scene()->items()) { + if (Node *node = qgraphicsitem_cast(item)) + nodes << node; + } + + foreach (Node *node, nodes) + node->calculateForces(); + + bool itemsMoved = false; + foreach (Node *node, nodes) { + if (node->advance()) + itemsMoved = true; + } + + if (!itemsMoved) { + killTimer(timerId); + timerId = 0; + } +} + +void GraphWidget::wheelEvent(QWheelEvent *event) +{ + scaleView(pow((double)2, -event->delta() / 240.0)); +} + +void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect) +{ + //Q_UNUSED(rect); + + // Shadow + QRectF sceneRect = rect;//this->sceneRect(); + QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height()); + QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5); + if (rightShadow.intersects(rect) || rightShadow.contains(rect)) + painter->fillRect(rightShadow, Qt::darkGray); + if (bottomShadow.intersects(rect) || bottomShadow.contains(rect)) + painter->fillRect(bottomShadow, Qt::darkGray); + + // Fill + QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight()); + gradient.setColorAt(0, Qt::white); + gradient.setColorAt(1, Qt::lightGray); + painter->fillRect(rect.intersect(sceneRect), gradient); + painter->setBrush(Qt::NoBrush); + painter->drawRect(sceneRect); + +#if !defined(Q_OS_SYMBIAN) && !defined(Q_WS_MAEMO_5) + // Text + QRectF textRect(sceneRect.left() + 4, sceneRect.top() + 4, + sceneRect.width() - 4, sceneRect.height() - 4); + QString message(tr("Click and drag the nodes around, and zoom with the mouse " + "wheel or the '+' and '-' keys")); + + QFont font = painter->font(); + font.setBold(true); + font.setPointSize(14); + painter->setFont(font); + painter->setPen(Qt::lightGray); + painter->drawText(textRect.translated(2, 2), message); + painter->setPen(Qt::black); + painter->drawText(textRect, message); +#endif +} + +void GraphWidget::scaleView(qreal scaleFactor) +{ + qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width(); + if (factor < 0.07 || factor > 100) + return; + + scale(scaleFactor, scaleFactor); +} + +void GraphWidget::shuffle() +{ + foreach (QGraphicsItem *item, scene()->items()) { + if (qgraphicsitem_cast(item)) + item->setPos(-150 + qrand() % 300, -150 + qrand() % 300); + } +} + +void GraphWidget::zoomIn() +{ + scaleView(qreal(1.2)); +} + +void GraphWidget::zoomOut() +{ + scaleView(1 / qreal(1.2)); +} diff --git a/appli/cpPipelineEditor/GraphWidget.h b/appli/cpPipelineEditor/GraphWidget.h new file mode 100644 index 0000000..3ccecc1 --- /dev/null +++ b/appli/cpPipelineEditor/GraphWidget.h @@ -0,0 +1,100 @@ +/**************************************************************************** + ** + ** Copyright (C) 2015 The Qt Company Ltd. + ** Contact: http://www.qt.io/licensing/ + ** + ** This file is part of the examples of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of The Qt Company Ltd nor the names of its + ** contributors may be used to endorse or promote products derived + ** from this software without specific prior written permission. + ** + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#ifndef GRAPHWIDGET_H +#define GRAPHWIDGET_H + +#include +#include + +class Node; +class Edge; +namespace cpPlugins +{ + namespace Interface + { + class Workspace; + } +} + +class GraphWidget + : public QGraphicsView +{ + Q_OBJECT; + +public: + typedef + cpExtensions::DataStructures:: + Graph< Node*, Edge*, std::string > + TGraph; + +public: + GraphWidget(QWidget *parent = 0); + + cpPlugins::Interface::Workspace* workspace( ); + const cpPlugins::Interface::Workspace* workspace( ) const; + void setWorkspace( cpPlugins::Interface::Workspace* ws ); + + void draw( ); + + void itemMoved(); + +public slots: + void shuffle(); + void zoomIn(); + void zoomOut(); + +protected: + void keyPressEvent(QKeyEvent *event); + void timerEvent(QTimerEvent *event); + void wheelEvent(QWheelEvent *event); + void drawBackground(QPainter *painter, const QRectF &rect); + + void scaleView(qreal scaleFactor); + +private: + int timerId; + Node *centerNode; + + cpPlugins::Interface::Workspace* m_Workspace; + TGraph::Pointer m_Graph; +}; + +#endif diff --git a/appli/cpPipelineEditor/Node.cxx b/appli/cpPipelineEditor/Node.cxx new file mode 100644 index 0000000..2ecb9e5 --- /dev/null +++ b/appli/cpPipelineEditor/Node.cxx @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +#include "Edge.h" +#include "Node.h" +#include "GraphWidget.h" + +Node::Node(GraphWidget *graphWidget, const std::string& label) + : graph(graphWidget), + m_Label( label ) +{ + setFlag(ItemIsMovable); + setFlag(ItemSendsGeometryChanges); + setCacheMode(DeviceCoordinateCache); + setZValue(-1); + this->setToolTip( this->m_Label.c_str( ) ); +} + +void Node::addEdge(Edge *edge) +{ + edgeList << edge; + edge->adjust(); +} + +QList Node::edges() const +{ + return edgeList; +} + +void Node::calculateForces() +{ + if (!scene() || scene()->mouseGrabberItem() == this) { + newPos = pos(); + return; + } + + // Sum up all forces pushing this item away + qreal xvel = 0; + qreal yvel = 0; + foreach (QGraphicsItem *item, scene()->items()) { + Node *node = qgraphicsitem_cast(item); + if (!node) + continue; + + QPointF vec = mapToItem(node, 0, 0); + qreal dx = vec.x(); + qreal dy = vec.y(); + double l = 2.0 * (dx * dx + dy * dy); + if (l > 0) { + xvel += (dx * 150.0) / l; + yvel += (dy * 150.0) / l; + } + } + + // Now subtract all forces pulling items together + double weight = (edgeList.size() + 1) * 10; + foreach (Edge *edge, edgeList) { + QPointF vec; + if (edge->sourceNode() == this) + vec = mapToItem(edge->destNode(), 0, 0); + else + vec = mapToItem(edge->sourceNode(), 0, 0); + xvel -= vec.x() / weight; + yvel -= vec.y() / weight; + } + + if (qAbs(xvel) < 0.1 && qAbs(yvel) < 0.1) + xvel = yvel = 0; + + QRectF sceneRect = scene()->sceneRect(); + newPos = pos() + QPointF(xvel, yvel); + newPos.setX(qMin(qMax(newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10)); + newPos.setY(qMin(qMax(newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10)); + + newPos = pos(); // + QPointF(xvel, yvel); +} + +bool Node::advance() +{ + if (newPos == pos()) + return false; + + setPos(newPos); + return true; +} + +QRectF Node::boundingRect() const +{ +#if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5) + // Add some extra space around the circle for easier touching with finger + qreal adjust = 30; + return QRectF( -10 - adjust, -10 - adjust, + 20 + adjust * 2, 20 + adjust * 2); +#else + qreal adjust = 2; + return QRectF( -10 - adjust, -10 - adjust, + 23 + adjust, 23 + adjust); +#endif +} + +QPainterPath Node::shape() const +{ + QPainterPath path; +#if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5) + // Add some extra space around the circle for easier touching with finger + path.addEllipse( -40, -40, 80, 80); +#else + path.addEllipse(-10, -10, 20, 20); +#endif + return path; +} + +void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) +{ + painter->setPen(Qt::NoPen); + painter->setBrush(Qt::darkGray); + painter->drawEllipse(-7, -7, 20, 20); + + QPointF text_point = this->boundingRect( ).bottomRight( ) + this->pos( ); + painter->drawText( text_point, this->m_Label.c_str( ) ); + std::cout << text_point.x( ) << " " << text_point.y( ) << std::endl; + + QRadialGradient gradient(-3, -3, 10); + if (option->state & QStyle::State_Sunken) { + gradient.setCenter(3, 3); + gradient.setFocalPoint(3, 3); + gradient.setColorAt(1, QColor(Qt::yellow).light(120)); + gradient.setColorAt(0, QColor(Qt::darkYellow).light(120)); + } else { + gradient.setColorAt(0, Qt::yellow); + gradient.setColorAt(1, Qt::darkYellow); + } + painter->setBrush(gradient); + + painter->setPen(QPen(Qt::black, 0)); + painter->drawEllipse(-10, -10, 20, 20); +} + +QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value) +{ + switch (change) { + case ItemPositionHasChanged: + foreach (Edge *edge, edgeList) + edge->adjust(); + graph->itemMoved(); + break; + default: + break; + }; + + return QGraphicsItem::itemChange(change, value); +} + +void Node::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + update(); + QGraphicsItem::mousePressEvent(event); +} + +void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + update(); + QGraphicsItem::mouseReleaseEvent(event); +} + diff --git a/appli/cpPipelineEditor/Node.h b/appli/cpPipelineEditor/Node.h new file mode 100644 index 0000000..088ade7 --- /dev/null +++ b/appli/cpPipelineEditor/Node.h @@ -0,0 +1,82 @@ +/**************************************************************************** + ** + ** Copyright (C) 2015 The Qt Company Ltd. + ** Contact: http://www.qt.io/licensing/ + ** + ** This file is part of the examples of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of The Qt Company Ltd nor the names of its + ** contributors may be used to endorse or promote products derived + ** from this software without specific prior written permission. + ** + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#ifndef NODE_H +#define NODE_H + +#include +#include + +class Edge; +class GraphWidget; +class QGraphicsSceneMouseEvent; + +class Node : public QGraphicsItem +{ +public: + Node(GraphWidget *graphWidget, const std::string& label ); + + void addEdge(Edge *edge); + QList edges() const; + + enum { Type = UserType + 1 }; + int type() const { return Type; } + + void calculateForces(); + bool advance(); + + QRectF boundingRect() const; + QPainterPath shape() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + +protected: + QVariant itemChange(GraphicsItemChange change, const QVariant &value); + + void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + +private: + QList edgeList; + QPointF newPos; + GraphWidget *graph; + std::string m_Label; +}; + +#endif diff --git a/appli/cpPipelineEditor/cpPipelineEditor.cxx b/appli/cpPipelineEditor/cpPipelineEditor.cxx new file mode 100644 index 0000000..3516270 --- /dev/null +++ b/appli/cpPipelineEditor/cpPipelineEditor.cxx @@ -0,0 +1,74 @@ +#include "cpPipelineEditor.h" +#include "ui_cpPipelineEditor.h" + +#include +#include +#include + +// ------------------------------------------------------------------------- +#define cpPipelineEditor_ConnectAction( ACTION ) \ + QObject::connect( \ + this->m_UI->Action##ACTION, SIGNAL( triggered( ) ), \ + this, SLOT( _Action##ACTION( ) ) \ + ) + +// ------------------------------------------------------------------------- +cpPipelineEditor:: +cpPipelineEditor( QWidget* parent ) + : QMainWindow( parent ), + m_UI( new Ui::cpPipelineEditor ), + m_Workspace( NULL ) +{ + this->m_UI->setupUi( this ); + + // Connect actions to slots + cpPipelineEditor_ConnectAction( OpenWorkspace ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor:: +~cpPipelineEditor( ) +{ + delete this->m_UI; + if( this->m_Workspace != NULL ) + delete this->m_Workspace; +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor:: +_ActionOpenWorkspace( ) +{ + QFileDialog dlg( this ); + dlg.setFileMode( QFileDialog::ExistingFile ); + dlg.setDirectory( "." ); + dlg.setNameFilter( + QFileDialog::tr( "Workspace file (*.xml);;All files (*)" ) + ); + dlg.setDefaultSuffix( QFileDialog::tr( "xml" ) ); + if( !( dlg.exec( ) ) ) + return; + std::string fname = dlg.selectedFiles( ).at( 0 ).toStdString( ); + + if( this->m_Workspace != NULL ) + delete this->m_Workspace; + this->m_Workspace = new cpPlugins::Interface::Workspace( ); + std::string err = this->m_Workspace->LoadWorkspace( fname ); + if( err == "" ) + { + this->m_UI->GraphCanvas->setWorkspace( this->m_Workspace ); + this->m_UI->GraphCanvas->draw( ); + } + else + { + delete this->m_Workspace; + this->m_Workspace = NULL; + QMessageBox::critical( + this, + QMessageBox::tr( "Error loading workspace" ), + QMessageBox::tr( err.c_str( ) ) + ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/appli/cpPipelineEditor/cpPipelineEditor.h b/appli/cpPipelineEditor/cpPipelineEditor.h new file mode 100644 index 0000000..2970093 --- /dev/null +++ b/appli/cpPipelineEditor/cpPipelineEditor.h @@ -0,0 +1,46 @@ +#ifndef __CPPIPELINEEDITOR__H__ +#define __CPPIPELINEEDITOR__H__ + +// Qt stuff +#include + +// ------------------------------------------------------------------------- +namespace Ui +{ + class cpPipelineEditor; +} + +namespace cpPlugins +{ + namespace Interface + { + class Workspace; + } +} + +/** + */ +class cpPipelineEditor + : public QMainWindow +{ + Q_OBJECT; + +public: + typedef cpPipelineEditor Self; + typedef QMainWindow Superclass; + +public: + explicit cpPipelineEditor( QWidget* parent = 0 ); + virtual ~cpPipelineEditor( ); + +protected slots: + void _ActionOpenWorkspace( ); + +private: + Ui::cpPipelineEditor* m_UI; + cpPlugins::Interface::Workspace* m_Workspace; +}; + +#endif // __CPPIPELINEEDITOR__H__ + +// eof - $RCSfile$ diff --git a/appli/cpPipelineEditor/cpPipelineEditor.ui b/appli/cpPipelineEditor/cpPipelineEditor.ui new file mode 100644 index 0000000..4b47461 --- /dev/null +++ b/appli/cpPipelineEditor/cpPipelineEditor.ui @@ -0,0 +1,69 @@ + + + cpPipelineEditor + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + + + + + + + + + + 0 + 0 + 800 + 27 + + + + + &File + + + + Workspace + + + + + + + + + + + + Open + + + + + Save + + + + + + GraphWidget + QWidget +
GraphWidget.h
+ 1 +
+
+ + +
diff --git a/appli/cpPipelineEditor/main.cxx b/appli/cpPipelineEditor/main.cxx new file mode 100644 index 0000000..7154469 --- /dev/null +++ b/appli/cpPipelineEditor/main.cxx @@ -0,0 +1,81 @@ +#include "cpPipelineEditor.h" +#include +#include + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + QApplication a( argc, argv ); + cpPipelineEditor w; + w.show( ); + + return( a.exec( ) ); +} + +// ------------------------------------------------------------------------- +#ifdef _WIN32 + +#include +#include +#include +#include + +/** + */ +class Win32CommandLineConverter +{ +private: + std::unique_ptr< char*[ ] > argv_; + std::vector< std::unique_ptr< char[ ] > > storage_; + +public: + Win32CommandLineConverter( ) + { + LPWSTR cmd_line = GetCommandLineW( ); + int argc; + LPWSTR* w_argv = CommandLineToArgvW( cmd_line, &argc ); + argv_ = std::unique_ptr< char*[ ] >( new char*[ argc ] ); + storage_.reserve( argc ); + for( int i = 0; i < argc; ++i ) + { + storage_.push_back( ConvertWArg( w_argv[ i ] ) ); + argv_[ i ] = storage_.back( ).get( ); + + } // rof + LocalFree( w_argv ); + } + int argc( ) const + { + return( static_cast< int >(storage_.size( ) ) ); + } + char** argv( ) const + { + return( argv_.get( ) ); + } + static std::unique_ptr< char[ ] > ConvertWArg( LPWSTR w_arg ) + { + int size = WideCharToMultiByte( + CP_UTF8, 0, w_arg, -1, nullptr, 0, nullptr, nullptr + ); + std::unique_ptr< char[ ] > ret( new char[ size ] ); + WideCharToMultiByte( + CP_UTF8, 0, w_arg, -1, ret.get( ), size, nullptr, nullptr + ); + return( ret ); + } +}; + +int CALLBACK WinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow + ) +{ + Win32CommandLineConverter cmd_line; + return( main( cmd_line.argc( ), cmd_line.argv( ) ) ); +} + +#endif + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/Graph.h b/lib/cpExtensions/DataStructures/Graph.h new file mode 100644 index 0000000..a23582f --- /dev/null +++ b/lib/cpExtensions/DataStructures/Graph.h @@ -0,0 +1,84 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__GRAPH__H__ +#define __CPEXTENSIONS__DATASTRUCTURES__GRAPH__H__ + +#include +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** + */ + template< class V, class C, class I = unsigned long > + class Graph + : public itk::LightObject + { + public: + typedef Graph Self; + typedef itk::LightObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef V TVertex; + typedef C TCost; + typedef I TIndex; + + // Graph types + typedef std::map< I, V > TVertices; + typedef std::vector< C > TEdges; + typedef std::map< I, TEdges > TMatrixRow; + typedef std::map< I, TMatrixRow > TMatrix; + + public: + itkNewMacro( Self ); + itkTypeMacro( Graph, itk::LightObject ); + + public: + typename TVertices::iterator BeginVertices( ); + typename TVertices::iterator EndVertices( ); + typename TVertices::const_iterator BeginVertices( ) const; + typename TVertices::const_iterator EndVertices( ) const; + + typename TMatrix::iterator BeginEdgesRows( ); + typename TMatrix::iterator EndEdgetsRows( ); + typename TMatrix::const_iterator BeginEdgesRows( ) const; + typename TMatrix::const_iterator EndEdgesRows( ) const; + + bool HasVertexIndex( const I& index ) const; + void InsertVertex( const I& index, V& vertex ); + V& GetVertex( const I& index ); + const V& GetVertex( const I& index ) const; + + void AddConnection( const I& orig, const I& dest, const C& cost ); + + std::set< I > GetSinks( ) const; + + protected: + Graph( ); + virtual ~Graph( ); + + private: + // Purposely not implemented + Graph( const Self& other ); + Self& operator=( const Self& other ); + + protected: + TVertices m_Vertices; + TMatrix m_Matrix; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__DATASTRUCTURES__GRAPH__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/Graph.hxx b/lib/cpExtensions/DataStructures/Graph.hxx new file mode 100644 index 0000000..9322977 --- /dev/null +++ b/lib/cpExtensions/DataStructures/Graph.hxx @@ -0,0 +1,150 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__GRAPH__HXX__ +#define __CPEXTENSIONS__DATASTRUCTURES__GRAPH__HXX__ + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +typename cpExtensions::DataStructures::Graph< V, C, I >:: +TVertices::iterator cpExtensions::DataStructures::Graph< V, C, I >:: +BeginVertices( ) +{ + return( this->m_Vertices.begin( ) ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +typename cpExtensions::DataStructures::Graph< V, C, I >:: +TVertices::iterator cpExtensions::DataStructures::Graph< V, C, I >:: +EndVertices( ) +{ + return( this->m_Vertices.end( ) ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +typename cpExtensions::DataStructures::Graph< V, C, I >:: +TVertices::const_iterator cpExtensions::DataStructures::Graph< V, C, I >:: +BeginVertices( ) const +{ + return( this->m_Vertices.begin( ) ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +typename cpExtensions::DataStructures::Graph< V, C, I >:: +TVertices::const_iterator cpExtensions::DataStructures::Graph< V, C, I >:: +EndVertices( ) const +{ + return( this->m_Vertices.end( ) ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +typename cpExtensions::DataStructures::Graph< V, C, I >:: +TMatrix::iterator cpExtensions::DataStructures::Graph< V, C, I >:: +BeginEdgesRows( ) +{ + return( this->m_Matrix.begin( ) ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +typename cpExtensions::DataStructures::Graph< V, C, I >:: +TMatrix::iterator cpExtensions::DataStructures::Graph< V, C, I >:: +EndEdgetsRows( ) +{ + return( this->m_Matrix.end( ) ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +typename cpExtensions::DataStructures::Graph< V, C, I >:: +TMatrix::const_iterator cpExtensions::DataStructures::Graph< V, C, I >:: +BeginEdgesRows( ) const +{ + return( this->m_Matrix.begin( ) ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +typename cpExtensions::DataStructures::Graph< V, C, I >:: +TMatrix::const_iterator cpExtensions::DataStructures::Graph< V, C, I >:: +EndEdgesRows( ) const +{ + return( this->m_Matrix.end( ) ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +bool cpExtensions::DataStructures::Graph< V, C, I >:: +HasVertexIndex( const I& index ) const +{ + return( this->m_Vertices.find( index ) != this->m_Vertices.end( ) ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +void cpExtensions::DataStructures::Graph< V, C, I >:: +InsertVertex( const I& index, V& vertex ) +{ + this->m_Vertices[ index ] = vertex; +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +V& cpExtensions::DataStructures::Graph< V, C, I >:: +GetVertex( const I& index ) +{ + return( this->m_Vertices[ index ] ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +const V& cpExtensions::DataStructures::Graph< V, C, I >:: +GetVertex( const I& index ) const +{ + return( this->m_Vertices[ index ] ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +void cpExtensions::DataStructures::Graph< V, C, I >:: +AddConnection( const I& orig, const I& dest, const C& cost ) +{ + this->m_Matrix[ orig ][ dest ].push_back( cost ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +std::set< I > cpExtensions::DataStructures::Graph< V, C, I >:: +GetSinks( ) const +{ + std::set< I > sinks; + + auto vIt = this->m_Vertices.begin( ); + for( ; vIt != this->m_Vertices.end( ); ++vIt ) + sinks.insert( vIt->first ); + auto mIt = this->m_Matrix.begin( ); + for( ; mIt != this->m_Matrix.end( ); ++mIt ) + sinks.erase( mIt->first ); + + return( sinks ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +cpExtensions::DataStructures::Graph< V, C, I >:: +Graph( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +cpExtensions::DataStructures::Graph< V, C, I >:: +~Graph( ) +{ +} + +#endif // __CPEXTENSIONS__DATASTRUCTURES__GRAPH__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/ImageInteractorStyle.cxx b/lib/cpExtensions/Interaction/ImageInteractorStyle.cxx index a23e374..0e6dce0 100644 --- a/lib/cpExtensions/Interaction/ImageInteractorStyle.cxx +++ b/lib/cpExtensions/Interaction/ImageInteractorStyle.cxx @@ -96,6 +96,24 @@ SetSeedWidgetCommand( vtkCommand* cmd ) AddObserver( vtkCommand::PlacePointEvent, cmd ); } +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Interaction::ImageInteractorStyle:: +GetNumberOfSeeds( ) const +{ + if( this->m_SeedWidget != NULL ) + return( this->m_SeedWidget->Representation->GetNumberOfSeeds( ) ); + else + return( 0 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageInteractorStyle:: +GetSeed( unsigned int id, double pos[ 3 ] ) const +{ + if( this->m_SeedWidget != NULL ) + this->m_SeedWidget->Representation->GetSeedWorldPosition( id, pos ); +} + // ------------------------------------------------------------------------- cpExtensions::Interaction::ImageInteractorStyle:: ImageInteractorStyle( ) diff --git a/lib/cpExtensions/Interaction/ImageInteractorStyle.h b/lib/cpExtensions/Interaction/ImageInteractorStyle.h index c18ab72..45a349f 100644 --- a/lib/cpExtensions/Interaction/ImageInteractorStyle.h +++ b/lib/cpExtensions/Interaction/ImageInteractorStyle.h @@ -67,6 +67,8 @@ namespace cpExtensions void SeedWidgetOn( ); void SeedWidgetOff( ); void SetSeedWidgetCommand( vtkCommand* cmd ); + unsigned int GetNumberOfSeeds( ) const; + void GetSeed( unsigned int id, double pos[ 3 ] ) const; protected: ImageInteractorStyle( ); diff --git a/lib/cpPlugins/Interface/CMakeLists.txt b/lib/cpPlugins/Interface/CMakeLists.txt index ae572cc..44eb019 100644 --- a/lib/cpPlugins/Interface/CMakeLists.txt +++ b/lib/cpPlugins/Interface/CMakeLists.txt @@ -21,6 +21,7 @@ IF(USE_QT4) SET( LIB_QT_UI BaseMPRWidget.ui + SimpleMPRWidget.ui ParametersListWidget.ui ) SET( @@ -28,12 +29,14 @@ IF(USE_QT4) ParametersListWidget.h ParametersQtDialog.h BaseMPRWidget.h + SimpleMPRWidget.h ) SET( LIB_QT_Sources ParametersListWidget.cxx ParametersQtDialog.cxx BaseMPRWidget.cxx + SimpleMPRWidget.cxx ) SET( LIB_QT_Resources diff --git a/lib/cpPlugins/Interface/SimpleMPRWidget.cxx b/lib/cpPlugins/Interface/SimpleMPRWidget.cxx new file mode 100644 index 0000000..c7c3058 --- /dev/null +++ b/lib/cpPlugins/Interface/SimpleMPRWidget.cxx @@ -0,0 +1,586 @@ +#include + +#ifdef cpPlugins_Interface_QT4 + +#include +#include +#include +#include +// TODO: #include +#include + +double cpPlugins::Interface::SimpleMPRWidget:: +cm_Colors[ 8 ][ 3 ] = +{ + { 1.0, 0.0, 0.0 }, + { 0.0, 1.0, 0.0 }, + { 0.0, 0.0, 1.0 }, + { 0.0, 1.0, 1.0 }, + { 1.0, 0.0, 1.0 }, + { 1.0, 1.0, 0.0 }, + { 1.0, 0.5, 0.0 }, + { 1.0, 0.0, 0.5 } +}; + +// ------------------------------------------------------------------------- +cpPlugins::Interface::SimpleMPRWidget:: +SimpleMPRWidget( QWidget* parent ) + : QWidget( parent ), + m_UI( new Ui::SimpleMPRWidget ), + m_MainImage( "" ) +{ + this->m_UI->setupUi( this ); + + // Configure VTK widgets + this->m_VTK[ 0 ] = this->m_UI->VTK01; + this->m_VTK[ 1 ] = this->m_UI->VTK00; + this->m_VTK[ 2 ] = this->m_UI->VTK10; + this->m_VTK[ 3 ] = this->m_UI->VTK11; + + this->m_MPRObjects = vtkSmartPointer< TMPRObjects >::New( ); + this->m_MPRObjects->SetRenderWindows( + this->m_VTK[ 0 ]->GetRenderWindow( ), + this->m_VTK[ 1 ]->GetRenderWindow( ), + this->m_VTK[ 2 ]->GetRenderWindow( ), + this->m_VTK[ 3 ]->GetRenderWindow( ) + ); + + // Connect slots + QObject::connect( + this->m_UI->TopSplitter, SIGNAL( splitterMoved( int, int ) ), + this, SLOT( _SyncBottom( int, int ) ) + ); + QObject::connect( + this->m_UI->BottomSplitter, SIGNAL( splitterMoved( int, int ) ), + this, SLOT( _SyncTop( int, int ) ) + ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface::SimpleMPRWidget:: +~SimpleMPRWidget( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface::SimpleMPRWidget:: +AddData( + cpPlugins::Interface::DataObject* data, const std::string& name, + const std::string& parent + ) +{ + if( name == "" ) + return( false ); + + auto iIt = this->m_Data.find( name ); + if( iIt == this->m_Data.end( ) ) + { + if( parent != "" ) + { + auto pIt = this->m_Data.find( parent ); + if( pIt == this->m_Data.end( ) ) + return( false ); + + } // fi + + // Add new data + this->m_Data[ name ].SetSourceDataObject( data ); + + // Add to tree view + // TODO: this->_UpdateTreeItem( name, parent ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +const std::string& cpPlugins::Interface::SimpleMPRWidget:: +GetMainImage( ) const +{ + return( this->m_MainImage ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface::SimpleMPRWidget:: +SetMainImage( const std::string& name ) +{ + auto iIt = this->m_Data.find( name ); + if( iIt != this->m_Data.end( ) ) + { + if( iIt->second.Tag == Data::IMAGE ) + { + this->m_MainImage = name; + return( true ); + } + else + return( false ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::SimpleMPRWidget:: +DeleteData( const std::string& name ) +{ + auto iIt = this->m_Data.find( name ); + if( iIt != this->m_Data.end( ) ) + { + this->m_Data.erase( iIt ); + + // Get children + std::vector< std::string > to_erase; + auto tIt = this->m_Tree.begin( ); + for( ; tIt != this->m_Tree.end( ); ++tIt ) + if( tIt->second == name ) + to_erase.push_back( tIt->first ); + + // Delete from tree + tIt = this->m_Tree.find( name ); + if( tIt != this->m_Tree.end( ) ) + this->m_Tree.erase( tIt ); + + // Recursive erase + auto dIt = to_erase.begin( ); + for( ; dIt != to_erase.end( ); ++dIt ) + this->DeleteData( *dIt ); + + // Delete from tree widget + /* TODO + QTreeWidgetItem* item = this->_FindItemInTree( name ); + if( item != NULL ) + this->m_UI->LoadedData->removeItemWidget( item, 0 ); + */ + + // Reset main image, just in case + if( this->m_Data.size( ) == 0 ) + this->m_MainImage = ""; + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::SimpleMPRWidget:: +DeleteAllData( ) +{ + this->m_MPRObjects->Clear( ); + this->m_Data.clear( ); + this->m_Tree.clear( ); + // TODO: this->m_UI->LoadedData->clear( ); + this->m_MainImage = ""; +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::SimpleMPRWidget:: +SetDataColor( + const std::string& name, const double& r, const double& g, const double& b + ) +{ + /* + auto iIt = this->m_Data.find( name ); + if( iIt == this->m_Data.end( ) ) + return; + + if( iIt->second.Tag == Data::IMAGE ) + { + } + else if( iIt->second.Tag == Data::MESH ) + { + } // fi + */ +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::SimpleMPRWidget:: +ShowData( const std::string& name ) +{ + auto iIt = this->m_Data.find( name ); + if( iIt == this->m_Data.end( ) ) + return; + + if( iIt->second.Tag == Data::IMAGE ) + { + if( name == this->m_MainImage ) + this->m_MPRObjects->SetInputImage( iIt->second.Image ); + else + { + unsigned int i = ( this->m_MPRObjects->GetNumberOfImages( ) - 1 ) % 8; + this->m_MPRObjects->AddBinaryImage( + iIt->second.Image, + Self::cm_Colors[ i ][ 0 ], + Self::cm_Colors[ i ][ 1 ], + Self::cm_Colors[ i ][ 2 ] + ); + } + this->m_MPRObjects->Show( ); + } + else if( iIt->second.Tag == Data::MESH ) + { + /* TODO + vtkRenderer* ren = + this->m_VTK[ 3 ]->GetRenderWindow( )->GetRenderers( )->GetFirstRenderer( ); + if( ren == NULL ) + return; + ren->AddActor( iIt->second.GetMeshActor( ) ); + this->m_VTK[ 3 ]->GetRenderWindow( )->Render( ); + */ + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::SimpleMPRWidget:: +HideData( const std::string& name ) +{ +} + +// ------------------------------------------------------------------------- +vtkRenderWindowInteractor* cpPlugins::Interface::SimpleMPRWidget:: +GetInteractor( unsigned int i ) +{ + if( i < 4 ) + { + if( this->m_VTK[ i ] != NULL ) + return( this->m_VTK[ i ]->GetInteractor( ) ); + else + return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +/* + bool cpPlugins::Interface::SimpleMPRWidget:: + ShowImage( + vtkImageData* image, + const std::string& name, + const std::string& parent + ) + { + // Update tree view + QTreeWidgetItem* new_item = this->_UpdateTreeItem( name, parent ); + if( new_item == NULL ) + return( false ); + + // Associate new data + this->m_Images[ name ] = image; + this->m_Tree[ name ] = parent; + + // Show image and return + this->m_MPRObjects->AddImage( image ); + return( true ); + } + + // ------------------------------------------------------------------------- + bool cpPlugins::Interface::SimpleMPRWidget:: + ShowImage( + vtkImageData* image, + const std::string& name, + const std::string& parent, + const double& r, const double& g, const double& b + ) + { + // Update tree view + QTreeWidgetItem* new_item = this->_UpdateTreeItem( name, parent ); + if( new_item == NULL ) + return( false ); + + // Associate new data + this->m_Images[ name ] = image; + this->m_Tree[ name ] = parent; + + // Show image and return + this->m_MPRObjects->AddImage( image ); + return( true ); + } + + // ------------------------------------------------------------------------- + bool cpPlugins::Interface::SimpleMPRWidget:: + ShowMesh( + vtkPolyData* mesh, + const std::string& name, + const std::string& parent + ) + { + // Update tree view + QTreeWidgetItem* new_item = this->_UpdateTreeItem( name, parent ); + if( new_item == NULL ) + return( false ); + + // Associate new data + PolyDataActor* actor = new PolyDataActor( mesh ); + this->m_Meshes[ name ] = actor; + this->m_Tree[ name ] = parent; + + // Show mesh + this->_Add3DActor( actor->Actor ); + return( true ); + } + + // ------------------------------------------------------------------------- + bool cpPlugins::Interface::SimpleMPRWidget:: + ShowMesh( + vtkPolyData* mesh, + const std::string& name, + const std::string& parent, + const double& r, const double& g, const double& b + ) + { + return false; + } + + // ------------------------------------------------------------------------- + void cpPlugins::Interface::SimpleMPRWidget:: + ClearAll( ) + { + this->m_MPRObjects->ClearAll( ); + this->m_Images.clear( ); + this->m_Meshes.clear( ); + } +*/ + +// ------------------------------------------------------------------------- +std::string cpPlugins::Interface::SimpleMPRWidget:: +GetSelectedData( ) const +{ + /* TODO + QTreeWidgetItem* item = this->m_UI->LoadedData->currentItem( ); + if( item != NULL ) + return( item->text( 0 ).toStdString( ) ); + else + */ + return( "" ); +} + +// ------------------------------------------------------------------------- +/* TODO +QTreeWidgetItem* cpPlugins::Interface::SimpleMPRWidget:: +_FindItemInTree( const std::string& name ) const +{ + QList< QTreeWidgetItem* > items = + this->m_UI->LoadedData->findItems( + name.c_str( ), Qt::MatchExactly | Qt::MatchRecursive + ); + if( items.size( ) > 0 ) + return( items[ 0 ] ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +QTreeWidgetItem* cpPlugins::Interface::SimpleMPRWidget:: +_UpdateTreeItem( const std::string& name, const std::string& parent ) +{ + // Update tree view + QTreeWidgetItem* new_item = NULL; + if( parent != "" ) + { + QTreeWidgetItem* parent_item = this->_FindItemInTree( parent ); + if( parent_item != NULL ) + { + QTreeWidgetItem* old_item = this->_FindItemInTree( name ); + if( old_item == NULL ) + { + new_item = + new QTreeWidgetItem( parent_item, QStringList( name.c_str( ) ) ); + parent_item->setExpanded( true ); + + } // fi + + } // fi + } + else + { + new_item = new QTreeWidgetItem( + ( QTreeWidgetItem* )( NULL ), QStringList( name.c_str( ) ) + ); + this->m_UI->LoadedData->addTopLevelItem( new_item ); + + } // fi + return( new_item ); +} +*/ + +// ------------------------------------------------------------------------- +/* + void cpPlugins::Interface::SimpleMPRWidget:: + _Add3DActor( vtkProp3D* prop ) + { + vtkRenderer* ren = + this->m_VTK[ 3 ]->GetRenderWindow( )->GetRenderers( )->GetFirstRenderer( ); + if( ren == NULL ) + return; + ren->AddActor( prop ); + this->m_VTK[ 3 ]->GetRenderWindow( )->Render( ); + } +*/ + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::SimpleMPRWidget:: +_SyncBottom( int a, int b ) +{ + this->m_UI->BottomSplitter->setSizes( this->m_UI->TopSplitter->sizes( ) ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::SimpleMPRWidget:: +_SyncTop( int a, int b ) +{ + this->m_UI->TopSplitter->setSizes( this->m_UI->BottomSplitter->sizes( ) ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface::SimpleMPRWidget::PolyDataActor:: +PolyDataActor( ) + : Mesh( NULL ), + Normals( NULL ), + Stripper( NULL ), + Mapper( NULL ), + Actor( NULL ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface::SimpleMPRWidget::PolyDataActor:: +~PolyDataActor( ) +{ + if( this->Actor != NULL ) this->Actor->Delete( ); + if( this->Mapper != NULL ) this->Mapper->Delete( ); + if( this->Stripper != NULL ) this->Stripper->Delete( ); + if( this->Normals != NULL ) this->Normals->Delete( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::SimpleMPRWidget::PolyDataActor:: +Configure( vtkPolyData* pd ) +{ + if( pd == NULL ) + return; + + double range[ 2 ]; + pd->GetScalarRange( range ); + + this->Normals = vtkPolyDataNormals::New( ); + this->Stripper = vtkStripper::New( ); + this->Mapper = vtkPolyDataMapper::New( ); + this->Actor = vtkQuadricLODActor::New( ); + + this->Mesh = pd; + this->Normals->SetInputData( pd ); + this->Normals->SetFeatureAngle( 60.0 ); + this->Stripper->SetInputConnection( this->Normals->GetOutputPort( ) ); + this->Mapper->SetInputConnection( this->Stripper->GetOutputPort( ) ); + this->Mapper->UseLookupTableScalarRangeOff( ); + this->Mapper->SetScalarRange( + range[ 0 ], ( ( range[ 1 ] - range[ 0 ] ) * 0.75 ) + range[ 0 ] + ); + this->Actor->SetMapper( this->Mapper ); + this->Actor->DeferLODConstructionOff( ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface::SimpleMPRWidget::Data:: +Data( ) +{ + this->Tag = Data::IMAGE; + this->Source = NULL; + this->Image = NULL; +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface::SimpleMPRWidget::Data:: +~Data( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface::SimpleMPRWidget:: +Data& cpPlugins::Interface::SimpleMPRWidget::Data:: +operator=( const Data& data ) +{ + this->Tag = data.Tag; + this->Source = data.Source; + if( this->Tag == Data::IMAGE ) + this->Image = data.Image; + else if( this->Tag == Data::MESH ) + this->Mesh = data.Mesh; + return( *this ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface:: +DataObject* cpPlugins::Interface::SimpleMPRWidget::Data:: +GetSourceDataObject( ) +{ + return( this->Source ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Interface:: +DataObject* cpPlugins::Interface::SimpleMPRWidget::Data:: +GetSourceDataObject( ) const +{ + return( this->Source ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::SimpleMPRWidget::Data:: +SetSourceDataObject( cpPlugins::Interface::DataObject* dobj ) +{ + typedef cpPlugins::Interface::Image _TImage; + typedef cpPlugins::Interface::Mesh _TMesh; + + this->Source = dobj; + _TImage* image = dynamic_cast< _TImage* >( dobj ); + if( image != NULL ) + { + this->Tag = Data::IMAGE; + this->Image = image->GetVTK< vtkImageData >( ); + } + else + { + _TMesh* mesh = dynamic_cast< _TMesh* >( dobj ); + if( mesh == NULL ) + return; + + this->Tag = Data::MESH; + this->Mesh.Configure( mesh->GetVTK< vtkPolyData >( ) ); + + } // fi +} + +// ------------------------------------------------------------------------- +vtkImageData* cpPlugins::Interface::SimpleMPRWidget::Data:: +GetImage( ) +{ + if( this->Tag == Data::IMAGE ) + return( this->Image ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +vtkPolyData* cpPlugins::Interface::SimpleMPRWidget::Data:: +GetMesh( ) +{ + if( this->Tag == Data::MESH ) + return( this->Mesh.Mesh ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +vtkProp* cpPlugins::Interface::SimpleMPRWidget::Data:: +GetMeshActor( ) +{ + if( this->Tag == Data::MESH ) + return( this->Mesh.Actor ); + else + return( NULL ); +} + +#endif // cpPlugins_Interface_QT4 + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface/SimpleMPRWidget.h b/lib/cpPlugins/Interface/SimpleMPRWidget.h new file mode 100644 index 0000000..7fe49b6 --- /dev/null +++ b/lib/cpPlugins/Interface/SimpleMPRWidget.h @@ -0,0 +1,158 @@ +#ifndef __CPPLUGINS__INTERFACE__SIMPLEMPRWIDGET__H__ +#define __CPPLUGINS__INTERFACE__SIMPLEMPRWIDGET__H__ + +#include +#include + +#ifdef cpPlugins_Interface_QT4 + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +// ------------------------------------------------------------------------- +class QTreeWidgetItem; +class QVTKWidget; + +namespace Ui +{ + class SimpleMPRWidget; +} + +// ------------------------------------------------------------------------- +namespace cpPlugins +{ + namespace Interface + { + // Some forward declarations + class DataObject; + + /** + */ + class cpPlugins_Interface_EXPORT SimpleMPRWidget + : public QWidget + { + Q_OBJECT; + + public: + typedef SimpleMPRWidget Self; + typedef cpExtensions::Visualization::MPRObjects TMPRObjects; + + typedef TMPRObjects::TStyle TStyle; + typedef TMPRObjects::TMouseCommand TMouseCommand; + typedef TMPRObjects::TMouseWheelCommand TMouseWheelCommand; + typedef TMPRObjects::TKeyCommand TKeyCommand; + typedef TMPRObjects::TVoidCommand TVoidCommand; + typedef TMPRObjects::TMouseMoveCommand TMouseMoveCommand; + typedef TMPRObjects::TMouseClickCommand TMouseClickCommand; + typedef TMPRObjects::TMouseDoubleClickCommand TMouseDoubleClickCommand; + typedef TMPRObjects::TExposeCommand TExposeCommand; + typedef TMPRObjects::TConfigureCommand TConfigureCommand; + typedef TMPRObjects::TEnterCommand TEnterCommand; + typedef TMPRObjects::TLeaveCommand TLeaveCommand; + + public: + explicit SimpleMPRWidget( QWidget* parent = 0 ); + virtual ~SimpleMPRWidget( ); + + // Data management + bool AddData( + DataObject* data, const std::string& name, + const std::string& parent + ); + const std::string& GetMainImage( ) const; + bool SetMainImage( const std::string& name ); + void DeleteData( const std::string& name ); + void DeleteAllData( ); + + // Some visualization accessors + void SetDataColor( + const std::string& name, + const double& r, const double& g, const double& b + ); + void ShowData( const std::string& name ); + void HideData( const std::string& name ); + + vtkRenderWindowInteractor* GetInteractor( unsigned int i ); + + // Visual objects accessors + std::string GetSelectedData( ) const; + + protected: + /* TODO + QTreeWidgetItem* _FindItemInTree( const std::string& name ) const; + QTreeWidgetItem* _UpdateTreeItem( + const std::string& name, + const std::string& parent + ); + */ + + private slots: + void _SyncBottom( int a, int b ); + void _SyncTop( int a, int b ); + + protected: + static double cm_Colors[ 8 ][ 3 ]; + + Ui::SimpleMPRWidget* m_UI; + vtkSmartPointer< TMPRObjects > m_MPRObjects; + QVTKWidget* m_VTK[ 4 ]; + + struct PolyDataActor + { + vtkPolyData* Mesh; + vtkPolyDataNormals* Normals; + vtkStripper* Stripper; + vtkPolyDataMapper* Mapper; + vtkQuadricLODActor* Actor; + + PolyDataActor( ); + virtual ~PolyDataActor( ); + void Configure( vtkPolyData* pd ); + }; + + struct Data + { + enum { IMAGE, MESH } Tag; + DataObject* Source; + vtkImageData* Image; + PolyDataActor Mesh; + + Data( ); + virtual ~Data( ); + + Data& operator=( const Data& data ); + + DataObject* GetSourceDataObject( ); + const DataObject* GetSourceDataObject( ) const; + void SetSourceDataObject( DataObject* dobj ); + + vtkImageData* GetImage( ); + vtkPolyData* GetMesh( ); + vtkProp* GetMeshActor( ); + }; + + std::string m_MainImage; + std::map< std::string, Data > m_Data; + std::map< std::string, std::string > m_Tree; + }; + + } // ecapseman + +} // ecapseman + +#endif // cpPlugins_Interface_QT4 + +#endif // __CPPLUGINS__INTERFACE__SIMPLEMPRWIDGET__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface/SimpleMPRWidget.ui b/lib/cpPlugins/Interface/SimpleMPRWidget.ui new file mode 100644 index 0000000..c8246e1 --- /dev/null +++ b/lib/cpPlugins/Interface/SimpleMPRWidget.ui @@ -0,0 +1,96 @@ + + + SimpleMPRWidget + + + + 0 + 0 + 424 + 424 + + + + Form + + + + + + + 406 + 406 + + + + Qt::Vertical + + + + + 406 + 200 + + + + Qt::Horizontal + + + + + 200 + 200 + + + + + + + 200 + 200 + + + + + + + + 406 + 200 + + + + Qt::Horizontal + + + + + 200 + 200 + + + + + + + 200 + 200 + + + + + + + + + + + QVTKWidget + QWidget +
QVTKWidget.h
+ 1 +
+
+ + +
diff --git a/lib/cpPlugins/Interface/Workspace.cxx b/lib/cpPlugins/Interface/Workspace.cxx index 9e8d4e1..4e5f51a 100644 --- a/lib/cpPlugins/Interface/Workspace.cxx +++ b/lib/cpPlugins/Interface/Workspace.cxx @@ -5,6 +5,7 @@ cpPlugins::Interface::Workspace:: Workspace( ) : m_LastLoadedPlugin( "" ) { + this->m_Graph = TGraph::New( ); } // ------------------------------------------------------------------------- @@ -104,19 +105,35 @@ GetLoadedPluginFilters( const std::string& category ) const return( EMPTY ); } +// ------------------------------------------------------------------------- +cpPlugins::Interface::Workspace:: +TGraph* cpPlugins::Interface::Workspace:: +GetGraph( ) +{ + return( this->m_Graph ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Interface::Workspace:: +TGraph* cpPlugins::Interface::Workspace:: +GetGraph( ) const +{ + return( this->m_Graph ); +} + // ------------------------------------------------------------------------- bool cpPlugins::Interface::Workspace:: CreateFilter( const std::string& filter, const std::string& name ) { // Get or create new filter from name - auto vIt = this->m_Vertices.find( name ); - if( vIt == this->m_Vertices.end( ) ) + if( !( this->m_Graph->HasVertexIndex( name ) ) ) { - TFilter::Pointer o = this->m_Interface.CreateObject( filter ); - if( o.IsNotNull( ) ) + TFilter::Pointer f = this->m_Interface.CreateObject( filter ); + if( f.IsNotNull( ) ) { - o->SetName( name ); - this->m_Vertices[ name ] = o; + f->SetName( name ); + TObject::Pointer o = f.GetPointer( ); + this->m_Graph->InsertVertex( name, o ); return( true ); } else @@ -134,20 +151,21 @@ Connect( ) { // Get filters - auto oIt = this->m_Vertices.find( orig_filter ); - if( oIt == this->m_Vertices.end( ) ) - return( false ); - auto dIt = this->m_Vertices.find( dest_filter ); - if( dIt == this->m_Vertices.end( ) ) - return( false ); - TFilter* orig = dynamic_cast< TFilter* >( oIt->second.GetPointer( ) ); - TFilter* dest = dynamic_cast< TFilter* >( dIt->second.GetPointer( ) ); + TFilter* orig = + dynamic_cast< TFilter* >( + this->m_Graph->GetVertex( orig_filter ).GetPointer( ) + ); + TFilter* dest = + dynamic_cast< TFilter* >( + this->m_Graph->GetVertex( dest_filter ).GetPointer( ) + ); if( orig == NULL || dest == NULL ) return( false ); // Real connection dest->SetInput( input_name, orig->GetOutput< TData >( output_name ) ); - this->m_AdjMatrix[ orig_filter ][ dest_filter ].push_back( + this->m_Graph->AddConnection( + orig_filter, dest_filter, TConnection( output_name, input_name ) ); return( false ); @@ -158,15 +176,12 @@ cpPlugins::Interface::Workspace:: TParameters* cpPlugins::Interface::Workspace:: GetParameters( const std::string& name ) { - auto vIt = this->m_Vertices.find( name ); - if( vIt != this->m_Vertices.end( ) ) - { - TFilter* f = dynamic_cast< TFilter* >( vIt->second.GetPointer( ) ); - if( f != NULL ) - return( f->GetParameters( ) ); - else - return( NULL ); - } + TFilter* f = + dynamic_cast< TFilter* >( + this->m_Graph->GetVertex( name ).GetPointer( ) + ); + if( f != NULL ) + return( f->GetParameters( ) ); else return( NULL ); } @@ -176,16 +191,12 @@ const cpPlugins::Interface::Workspace:: TParameters* cpPlugins::Interface::Workspace:: GetParameters( const std::string& name ) const { - auto vIt = this->m_Vertices.find( name ); - if( vIt != this->m_Vertices.end( ) ) - { - const TFilter* f = - dynamic_cast< const TFilter* >( vIt->second.GetPointer( ) ); - if( f != NULL ) - return( f->GetParameters( ) ); - else - return( NULL ); - } + const TFilter* f = + dynamic_cast< const TFilter* >( + this->m_Graph->GetVertex( name ).GetPointer( ) + ); + if( f != NULL ) + return( f->GetParameters( ) ); else return( NULL ); } @@ -194,6 +205,7 @@ GetParameters( const std::string& name ) const bool cpPlugins::Interface::Workspace:: Reduce( const std::string& name ) { + return( false ); } // ------------------------------------------------------------------------- @@ -201,13 +213,7 @@ std::string cpPlugins::Interface::Workspace:: Execute( ) { // Find sinks - std::set< std::string > sinks; - auto vIt = this->m_Vertices.begin( ); - for( ; vIt != this->m_Vertices.end( ); ++vIt ) - sinks.insert( vIt->first ); - auto mIt = this->m_AdjMatrix.begin( ); - for( ; mIt != this->m_AdjMatrix.end( ); ++mIt ) - sinks.erase( mIt->first ); + std::set< std::string > sinks = this->m_Graph->GetSinks( ); // Update sinks std::string err = ""; @@ -226,13 +232,10 @@ std::string cpPlugins::Interface::Workspace:: Execute( const std::string& name ) { // Get filter - auto vIt = this->m_Vertices.find( name ); - if( vIt == this->m_Vertices.end( ) ) - return( - std::string( "cpPlugins::Interface::Workspace: No filter \"" ) + - name + std::string( "\"" ) + TFilter* f = + dynamic_cast< TFilter* >( + this->m_Graph->GetVertex( name ).GetPointer( ) ); - TFilter* f = dynamic_cast< TFilter* >( vIt->second.GetPointer( ) ); if( f == NULL ) return( std::string( "cpPlugins::Interface::Workspace: Vertex \"" ) + diff --git a/lib/cpPlugins/Interface/Workspace.h b/lib/cpPlugins/Interface/Workspace.h index 863d84e..9bad734 100644 --- a/lib/cpPlugins/Interface/Workspace.h +++ b/lib/cpPlugins/Interface/Workspace.h @@ -1,11 +1,11 @@ #ifndef __CPPLUGINS__INTERFACE__WORKSPACE__H__ #define __CPPLUGINS__INTERFACE__WORKSPACE__H__ +#include #include #include #include -#include #include #include @@ -27,12 +27,11 @@ namespace cpPlugins // Various types typedef std::set< std::string > TStringContainer; - // Graph types - typedef std::map< std::string, TObject::Pointer > TVertices; - typedef std::pair< std::string, std::string > TConnection; - typedef std::vector< TConnection > TConnections; - typedef std::map< std::string, TConnections > TAdjMatrixRow; - typedef std::map< std::string, TAdjMatrixRow > TAdjMatrix; + // Graph type + typedef std::pair< std::string, std::string > TConnection; + typedef + cpExtensions::DataStructures:: + Graph< TObject::Pointer, TConnection, std::string > TGraph; public: Workspace( ); @@ -53,6 +52,8 @@ namespace cpPlugins std::string SaveWorkspace( const std::string& fname ) const; // Graph management + TGraph* GetGraph( ); + const TGraph* GetGraph( ) const; bool CreateFilter( const std::string& filter, const std::string& name ); bool Connect( const std::string& orig_filter, const std::string& dest_filter, @@ -80,8 +81,7 @@ namespace cpPlugins std::map< std::string, TStringContainer > m_LoadedFilters; // Processing graph - TVertices m_Vertices; - TAdjMatrix m_AdjMatrix; + typename TGraph::Pointer m_Graph; }; } // ecapseman diff --git a/lib/cpPlugins/Plugins/BasicFilters/CMakeLists.txt b/lib/cpPlugins/Plugins/BasicFilters/CMakeLists.txt index 2482a0b..2d0392f 100644 --- a/lib/cpPlugins/Plugins/BasicFilters/CMakeLists.txt +++ b/lib/cpPlugins/Plugins/BasicFilters/CMakeLists.txt @@ -15,10 +15,12 @@ IF(USE_QT4) SET( LIB_QT_Headers MacheteFilter.h + DoubleFloodImageFilter.h ) SET( LIB_QT_Sources MacheteFilter.cxx + DoubleFloodImageFilter.cxx ) QT4_WRAP_CPP(LIB_QT_Wrapped_MOC_Sources ${LIB_QT_Headers}) diff --git a/lib/cpPlugins/Plugins/BasicFilters/DoubleFloodImageFilter.cxx b/lib/cpPlugins/Plugins/BasicFilters/DoubleFloodImageFilter.cxx new file mode 100644 index 0000000..af44e53 --- /dev/null +++ b/lib/cpPlugins/Plugins/BasicFilters/DoubleFloodImageFilter.cxx @@ -0,0 +1,347 @@ +#include "DoubleFloodImageFilter.h" +#include +#include +#include +#include + +#include + +#include +#include + +#ifdef cpPlugins_Interface_QT4 +#include + +// ------------------------------------------------------------------------- +cpPlugins::BasicFilters::DoubleFloodImageFilter_Dialog:: +DoubleFloodImageFilter_Dialog( + QWidget* parent, DoubleFloodImageFilter* filter, Qt::WindowFlags f + ) + : QDialog( parent, f | Qt::WindowStaysOnTopHint ), + m_Filter( filter ) +{ + this->m_Title = new QLabel( this ); + this->m_Title->setText( "Execute simple vessel segmentation filter" ); + + this->m_MainLayout = new QGridLayout( this ); + this->m_ToolsLayout = new QVBoxLayout( ); + this->m_ToolsLayout->addWidget( this->m_Title ); + this->m_MainLayout->addLayout( this->m_ToolsLayout, 0, 0, 1, 1 ); + + // Add buttons + QDialogButtonBox* bb = new QDialogButtonBox( + QDialogButtonBox::Cancel | QDialogButtonBox::Ok + ); + QObject::connect( bb, SIGNAL( accepted( ) ), this, SLOT( accept( ) ) ); + QObject::connect( bb, SIGNAL( rejected( ) ), this, SLOT( reject( ) ) ); + this->m_ToolsLayout->addWidget( bb ); +} + +// ------------------------------------------------------------------------- +cpPlugins::BasicFilters::DoubleFloodImageFilter_Dialog:: +~DoubleFloodImageFilter_Dialog( ) +{ + delete this->m_Title; + delete this->m_ToolsLayout; + delete this->m_MainLayout; +} + +// ------------------------------------------------------------------------- +void cpPlugins::BasicFilters::DoubleFloodImageFilter_Dialog:: +accept( ) +{ + // Get interactive widget + if( this->m_Filter == NULL ) + return; + + typedef cpExtensions::Interaction::ImageInteractorStyle _TImageStyle; + + // Activate seed widgets + auto iIt = this->m_Filter->m_Interactors.begin( ); + for( ; iIt != this->m_Filter->m_Interactors.end( ); ++iIt ) + { + _TImageStyle* istyle = + dynamic_cast< _TImageStyle* >( + ( *iIt )->GetInteractorStyle( ) + ); + if( istyle == NULL ) + continue; + unsigned int nSeeds = istyle->GetNumberOfSeeds( ); + for( unsigned int s = 0; s < nSeeds; ++s ) + { + double seed[ 3 ]; + istyle->GetSeed( s, seed ); + + } // rof + + } // rof + /* + vtkPlaneWidget* wdg = this->m_Filter->m_PlaneWidget; + if( wdg == NULL ) + return; + + // Get/Set plane parameters + double center[ 3 ], normal[ 3 ]; + wdg->GetCenter( center ); + wdg->GetNormal( normal ); + + this->m_Filter->GetParameters( )->SetPoint( "PlaneCenter", 3, center ); + this->m_Filter->GetParameters( )->SetVector( "PlaneNormal", 3, normal ); + + // Update filter + auto plugins = this->m_Filter->GetPlugins( ); + if( plugins != NULL ) + { + auto app = plugins->GetApplication( ); + if( app != NULL ) + app->UpdateActualFilter( ); + + } // fi + */ +} + +// ------------------------------------------------------------------------- +void cpPlugins::BasicFilters::DoubleFloodImageFilter_Dialog:: +reject( ) +{ + auto plugins = this->m_Filter->GetPlugins( ); + if( plugins != NULL ) + plugins->DeactivateFilter( ); + this->Superclass::reject( ); +} + +#endif // cpPlugins_Interface_QT4 + +// ------------------------------------------------------------------------- +cpPlugins::BasicFilters::DoubleFloodImageFilter:: +DialogResult cpPlugins::BasicFilters::DoubleFloodImageFilter:: +ExecConfigurationDialog( QWidget* parent ) +{ +#ifdef cpPlugins_Interface_QT4 + + typedef cpExtensions::Interaction::ImageInteractorStyle _TImageStyle; + + // Activate seed widgets + bool at_least_one = false; + auto iIt = this->m_Interactors.begin( ); + for( ; iIt != this->m_Interactors.end( ); ++iIt ) + { + _TImageStyle* istyle = + dynamic_cast< _TImageStyle* >( + ( *iIt )->GetInteractorStyle( ) + ); + if( istyle != NULL ) + { + istyle->SeedWidgetOn( ); + at_least_one = true; + + } // fi + + } // rof + if( !at_least_one ) + return( Self::DialogResult_Cancel ); + + // Create dialog + this->m_Dialog = new DoubleFloodImageFilter_Dialog( NULL, this ); + this->m_Dialog->show( ); + + return( Self::DialogResult_Modal ); +#else // cpPlugins_Interface_QT4 + return( Self::DialogResult_Cancel ); +#endif // cpPlugins_Interface_QT4 +} + +// ------------------------------------------------------------------------- +cpPlugins::BasicFilters::DoubleFloodImageFilter:: +DoubleFloodImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_MakeOutput< cpPlugins::Interface::Image >( "Output" ); + + double seed[ 3 ] = { double( 0 ) }; + this->m_Parameters->ConfigureAsPoint( "Seed0", 3, seed ); + this->m_Parameters->ConfigureAsPoint( "Seed1", 3, seed ); + this->m_Parameters->ConfigureAsReal( "Window", 0 ); + this->m_Parameters->ConfigureAsReal( "Level", 0 ); + this->m_Parameters->ConfigureAsUint( "InsideValue", 255 ); + this->m_Parameters->ConfigureAsUint( "OutsideValue", 0 ); +} + +// ------------------------------------------------------------------------- +cpPlugins::BasicFilters::DoubleFloodImageFilter:: +~DoubleFloodImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +std::string cpPlugins::BasicFilters::DoubleFloodImageFilter:: +_GenerateData( ) +{ + cpPlugins::Interface::Image* image = + this->GetInput< cpPlugins::Interface::Image >( "Input" ); + if( image == NULL ) + return( "DoubleFloodImageFilter: No input image." ); + + itk::DataObject* itk_image = NULL; + std::string r = ""; + cpPlugins_Image_Demangle_AllScalarTypes( 2, image, itk_image, r, _GD0 ); + else cpPlugins_Image_Demangle_AllScalarTypes( 3, image, itk_image, r, _GD0 ); + else r = "DoubleFloodImageFilter: Input image type not supported."; + return( r ); +} + +// ------------------------------------------------------------------------- +template< class I > +std::string cpPlugins::BasicFilters::DoubleFloodImageFilter:: +_GD0( itk::DataObject* image ) +{ + return( + this->_RealGD< I, itk::Image< unsigned char, I::ImageDimension > >( + image + ) + ); +} + +// ------------------------------------------------------------------------- +template< class I, class R = float > +class cpPlugins_BasicFilters_DoubleFloodImageFilter_Function + : public itk::ImageFunction< I, bool, R > +{ +public: + typedef cpPlugins_BasicFilters_DoubleFloodImageFilter_Function Self; + typedef itk::ImageFunction< I, bool, R > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::PointType TPoint; + typedef typename Superclass::IndexType TIndex; + typedef typename Superclass::ContinuousIndexType TCIndex; + +public: + itkNewMacro( Self ); + itkTypeMacro( + cpPlugins_BasicFilters_DoubleFloodImageFilter_Function, + itkImageFunction + ); + + itkSetMacro( Window, double ); + itkSetMacro( Level, double ); + +public: + virtual bool Evaluate( const TPoint& point ) const + { + return( true ); + } + virtual bool EvaluateAtIndex( const TIndex& index ) const + { + if( !( this->IsInsideBuffer( index ) ) ) + return( false ); + + const I* image = this->GetInputImage( ); + double w2 = this->m_Window / double( 2 ); + double min = this->m_Level - w2; + double max = this->m_Level + w2; + unsigned char val = double( 0 ); + double x = double( image->GetPixel( index ) ); + double m = double( 100 ) / this->m_Window; + double b = ( this->m_Window - ( double( 2 ) * this->m_Level ) ); + b *= double( 50 ) / this->m_Window; + if( x > min && x < max ) + val = ( unsigned char )( ( m * x ) + b ); + + if( this->m_Start ) + { + this->m_StartValue = val; + this->m_Start = false; + return( true ); + } + else + return( std::abs( this->m_StartValue - val ) <= 2 ); + } + virtual bool EvaluateAtContinuousIndex( const TCIndex& index ) const + { + return( true ); + } + +protected: + cpPlugins_BasicFilters_DoubleFloodImageFilter_Function( ) + : Superclass( ), + m_Window( double( 0 ) ), + m_Level( double( 0 ) ), + m_Start( true ) + { + } + virtual ~cpPlugins_BasicFilters_DoubleFloodImageFilter_Function( ) + { + } + +private: + // Purposely not implemented + cpPlugins_BasicFilters_DoubleFloodImageFilter_Function( const Self& other ); + Self& operator=( const Self& other ); + +protected: + double m_Window; + double m_Level; + mutable unsigned char m_StartValue; + mutable bool m_Start; +}; + +// ------------------------------------------------------------------------- +template< class I, class O > +inline std::string cpPlugins::BasicFilters::DoubleFloodImageFilter:: +_RealGD( itk::DataObject* image ) +{ + /* + typedef typename O::PixelType _OP; + typedef cpPlugins_BasicFilters_DoubleFloodImageFilter_Function< I > _F; + typedef itk::FloodFilledImageFunctionConditionalConstIterator< I, _F > _It; + + typename I::PointType pseed; + pseed = this->m_Parameters->GetPoint< typename I::PointType >( + "Seed", I::ImageDimension + ); + double window = this->m_Parameters->GetReal( "Window" ); + double level = this->m_Parameters->GetReal( "Level" ); + _OP in_val = _OP( this->m_Parameters->GetUint( "InsideValue" ) ); + _OP out_val = _OP( this->m_Parameters->GetUint( "OutsideValue" ) ); + + const I* in = dynamic_cast< const I* >( image ); + typename I::IndexType seed; + in->TransformPhysicalPointToIndex( pseed, seed ); + + typename O::Pointer out = O::New( ); + out->SetLargestPossibleRegion( in->GetLargestPossibleRegion( ) ); + out->SetRequestedRegion( in->GetRequestedRegion( ) ); + out->SetBufferedRegion( in->GetBufferedRegion( ) ); + out->SetOrigin( in->GetOrigin( ) ); + out->SetDirection( in->GetDirection( ) ); + out->SetSpacing( in->GetSpacing( ) ); + out->Allocate( ); + out->FillBuffer( out_val ); + + typename _F::Pointer f = _F::New( ); + f->SetInputImage( in ); + f->SetWindow( window ); + f->SetLevel( level ); + _It i( in, f ); + i.AddSeed( seed ); + + for( i.GoToBegin( ); !i.IsAtEnd( ); ++i ) + out->SetPixel( i.GetIndex( ), in_val ); + + // Connect output + cpPlugins::Interface::Image* out_port = + this->GetOutput< cpPlugins::Interface::Image >( "Output" ); + if( out_port != NULL ) + { + out_port->SetITK< O >( out ); + return( "" ); + } + else +*/ + return( "DoubleFloodImageFilter: output not correctly created." ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Plugins/BasicFilters/DoubleFloodImageFilter.h b/lib/cpPlugins/Plugins/BasicFilters/DoubleFloodImageFilter.h new file mode 100644 index 0000000..730ffff --- /dev/null +++ b/lib/cpPlugins/Plugins/BasicFilters/DoubleFloodImageFilter.h @@ -0,0 +1,108 @@ +#ifndef __CPPLUGINS__PLUGINS__DOUBLEFLOODIMAGEFILTER__H__ +#define __CPPLUGINS__PLUGINS__DOUBLEFLOODIMAGEFILTER__H__ + +#include +#include + +#ifdef cpPlugins_Interface_QT4 +#include +#include +#include +#include +#endif // cpPlugins_Interface_QT4 + +namespace cpPlugins +{ + namespace BasicFilters + { +#ifdef cpPlugins_Interface_QT4 + class DoubleFloodImageFilter; + + /** + */ + class DoubleFloodImageFilter_Dialog + : public QDialog + { + Q_OBJECT; + + public: + typedef QDialog Superclass; + + public: + DoubleFloodImageFilter_Dialog( + QWidget* parent, DoubleFloodImageFilter* filter, Qt::WindowFlags f = 0 + ); + virtual ~DoubleFloodImageFilter_Dialog( ); + + public slots: + virtual void accept( ); + virtual void reject( ); + + protected: + DoubleFloodImageFilter* m_Filter; + QLabel* m_Title; + QGridLayout* m_MainLayout; + QVBoxLayout* m_ToolsLayout; + }; +#endif // cpPlugins_Interface_QT4 + + /** + */ + class cpPluginsBasicFilters_EXPORT DoubleFloodImageFilter + : public cpPlugins::Interface::ImageToImageFilter + { + public: + typedef DoubleFloodImageFilter Self; + typedef cpPlugins::Interface::ImageToImageFilter Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( + DoubleFloodImageFilter, + cpPlugins::Interface::ImageToImageFilter + ); + cpPlugins_Id_Macro( + cpPlugins::BasicFilters::DoubleFloodImageFilter, + "ImageToBinaryImageFilter" + ); + + public: + virtual DialogResult ExecConfigurationDialog( QWidget* parent ); + + protected: + DoubleFloodImageFilter( ); + virtual ~DoubleFloodImageFilter( ); + + virtual std::string _GenerateData( ); + + template< class I > + inline std::string _GD0( itk::DataObject* image ); + + template< class I, class O > + inline std::string _RealGD( itk::DataObject* image ); + + private: + // Purposely not implemented + DoubleFloodImageFilter( const Self& ); + Self& operator=( const Self& ); + + protected: +#ifdef cpPlugins_Interface_QT4 + friend class DoubleFloodImageFilter_Dialog; + DoubleFloodImageFilter_Dialog* m_Dialog; +#endif // cpPlugins_Interface_QT4 + + }; + + // --------------------------------------------------------------------- + CPPLUGINS_INHERIT_PROVIDER( DoubleFloodImageFilter ); + + } // ecapseman + +} // ecapseman + +#endif // __CPPLUGINS__PLUGINS__DOUBLEFLOODIMAGEFILTER__H__ + +// eof - $RCSfile$