]> Creatis software - cpPlugins.git/commitdiff
Pipeline editor added.
authorLeonardo Florez-Valencia <florez-l@javeriana.edu.co>
Thu, 10 Dec 2015 00:22:50 +0000 (19:22 -0500)
committerLeonardo Florez-Valencia <florez-l@javeriana.edu.co>
Thu, 10 Dec 2015 00:22:50 +0000 (19:22 -0500)
25 files changed:
appli/CMakeLists.txt
appli/cpPipelineEditor/CMakeLists.txt [new file with mode: 0644]
appli/cpPipelineEditor/Edge.cxx [new file with mode: 0644]
appli/cpPipelineEditor/Edge.h [new file with mode: 0644]
appli/cpPipelineEditor/GraphWidget.cxx [new file with mode: 0644]
appli/cpPipelineEditor/GraphWidget.h [new file with mode: 0644]
appli/cpPipelineEditor/Node.cxx [new file with mode: 0644]
appli/cpPipelineEditor/Node.h [new file with mode: 0644]
appli/cpPipelineEditor/cpPipelineEditor.cxx [new file with mode: 0644]
appli/cpPipelineEditor/cpPipelineEditor.h [new file with mode: 0644]
appli/cpPipelineEditor/cpPipelineEditor.ui [new file with mode: 0644]
appli/cpPipelineEditor/main.cxx [new file with mode: 0644]
lib/cpExtensions/DataStructures/Graph.h [new file with mode: 0644]
lib/cpExtensions/DataStructures/Graph.hxx [new file with mode: 0644]
lib/cpExtensions/Interaction/ImageInteractorStyle.cxx
lib/cpExtensions/Interaction/ImageInteractorStyle.h
lib/cpPlugins/Interface/CMakeLists.txt
lib/cpPlugins/Interface/SimpleMPRWidget.cxx [new file with mode: 0644]
lib/cpPlugins/Interface/SimpleMPRWidget.h [new file with mode: 0644]
lib/cpPlugins/Interface/SimpleMPRWidget.ui [new file with mode: 0644]
lib/cpPlugins/Interface/Workspace.cxx
lib/cpPlugins/Interface/Workspace.h
lib/cpPlugins/Plugins/BasicFilters/CMakeLists.txt
lib/cpPlugins/Plugins/BasicFilters/DoubleFloodImageFilter.cxx [new file with mode: 0644]
lib/cpPlugins/Plugins/BasicFilters/DoubleFloodImageFilter.h [new file with mode: 0644]

index 2568ba0471039e5e1a052802f4e5ac4bd8673d57..6e0414cde64c3cc7d7213340cc8ca7dad3540b98 100644 (file)
@@ -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 (file)
index 0000000..5ecebcd
--- /dev/null
@@ -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 (file)
index 0000000..1442a61
--- /dev/null
@@ -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 <QPainter>
+
+#include "Edge.h"
+#include "Node.h"
+
+#include <math.h>
+
+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 (file)
index 0000000..49bf282
--- /dev/null
@@ -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 <QGraphicsItem>
+
+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 (file)
index 0000000..2eb9553
--- /dev/null
@@ -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 <QtGui>
+
+#include <cpPlugins/Interface/Workspace.h>
+
+#include <math.h>
+
+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<Node *> nodes;
+  foreach (QGraphicsItem *item, scene()->items()) {
+    if (Node *node = qgraphicsitem_cast<Node *>(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<Node *>(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 (file)
index 0000000..3ccecc1
--- /dev/null
@@ -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 <QtGui/QGraphicsView>
+#include <cpExtensions/DataStructures/Graph.h>
+
+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 (file)
index 0000000..2ecb9e5
--- /dev/null
@@ -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 <QGraphicsScene>
+#include <QGraphicsSceneMouseEvent>
+#include <QPainter>
+#include <QStyleOption>
+
+#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<Edge *> 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<Node *>(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 (file)
index 0000000..088ade7
--- /dev/null
@@ -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 <QGraphicsItem>
+#include <QList>
+
+class Edge;
+class GraphWidget;
+class QGraphicsSceneMouseEvent;
+
+class Node : public QGraphicsItem
+{
+public:
+  Node(GraphWidget *graphWidget, const std::string& label );
+
+  void addEdge(Edge *edge);
+  QList<Edge *> 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<Edge *> 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 (file)
index 0000000..3516270
--- /dev/null
@@ -0,0 +1,74 @@
+#include "cpPipelineEditor.h"
+#include "ui_cpPipelineEditor.h"
+
+#include <QFileDialog>
+#include <QMessageBox>
+#include <cpPlugins/Interface/Workspace.h>
+
+// -------------------------------------------------------------------------
+#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 (file)
index 0000000..2970093
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef __CPPIPELINEEDITOR__H__
+#define __CPPIPELINEEDITOR__H__
+
+// Qt stuff
+#include <QMainWindow>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..4b47461
--- /dev/null
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>cpPipelineEditor</class>
+ <widget class="QMainWindow" name="cpPipelineEditor">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>800</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="MainWidget">
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <widget class="GraphWidget" name="GraphCanvas" native="true"/>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="Menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>800</width>
+     <height>27</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="MenuFile">
+    <property name="title">
+     <string>&amp;File</string>
+    </property>
+    <widget class="QMenu" name="MenuWorkspace">
+     <property name="title">
+      <string>Workspace</string>
+     </property>
+     <addaction name="ActionOpenWorkspace"/>
+     <addaction name="ActionSaveWorkspace"/>
+    </widget>
+    <addaction name="MenuWorkspace"/>
+   </widget>
+   <addaction name="MenuFile"/>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <action name="ActionOpenWorkspace">
+   <property name="text">
+    <string>Open</string>
+   </property>
+  </action>
+  <action name="ActionSaveWorkspace">
+   <property name="text">
+    <string>Save</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>GraphWidget</class>
+   <extends>QWidget</extends>
+   <header>GraphWidget.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/appli/cpPipelineEditor/main.cxx b/appli/cpPipelineEditor/main.cxx
new file mode 100644 (file)
index 0000000..7154469
--- /dev/null
@@ -0,0 +1,81 @@
+#include "cpPipelineEditor.h"
+#include <cstdlib>
+#include <QApplication>
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+  QApplication a( argc, argv );
+  cpPipelineEditor w;
+  w.show( );
+
+  return( a.exec( ) );
+}
+
+// -------------------------------------------------------------------------
+#ifdef _WIN32
+
+#include <memory>
+#include <vector>
+#include <windows.h>
+#include <shellapi.h>
+
+/**
+ */
+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 (file)
index 0000000..a23582f
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef __CPEXTENSIONS__DATASTRUCTURES__GRAPH__H__
+#define __CPEXTENSIONS__DATASTRUCTURES__GRAPH__H__
+
+#include <map>
+#include <set>
+#include <vector>
+#include <itkLightObject.h>
+#include <itkObjectFactory.h>
+
+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 <cpExtensions/DataStructures/Graph.hxx>
+#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 (file)
index 0000000..9322977
--- /dev/null
@@ -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$
index a23e3749d6e2ae4828c86b1af652124c57c26bc3..0e6dce0235da38df90e2f4a6eb5e38bab91ec51b 100644 (file)
@@ -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( )
index c18ab724c6ff21584f5bd04f3930c93f8da5fa4e..45a349f8e46ceb42ee8b26b9f0b0bcacbb50acbf 100644 (file)
@@ -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( );
index ae572ccf77f142e5accb72bf24e20f307c4182b2..44eb019063bf6612b2796e32ccb57fb854e9e976 100644 (file)
@@ -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 (file)
index 0000000..c7c3058
--- /dev/null
@@ -0,0 +1,586 @@
+#include <cpPlugins/Interface/SimpleMPRWidget.h>
+
+#ifdef cpPlugins_Interface_QT4
+
+#include <cpPlugins/Interface/ui_SimpleMPRWidget.h>
+#include <cpPlugins/Interface/DataObject.h>
+#include <cpPlugins/Interface/Image.h>
+#include <cpPlugins/Interface/Mesh.h>
+// TODO: #include <QTreeWidgetItem>
+#include <vtkRendererCollection.h>
+
+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 (file)
index 0000000..7fe49b6
--- /dev/null
@@ -0,0 +1,158 @@
+#ifndef __CPPLUGINS__INTERFACE__SIMPLEMPRWIDGET__H__
+#define __CPPLUGINS__INTERFACE__SIMPLEMPRWIDGET__H__
+
+#include <cpPlugins/Interface/cpPlugins_Interface_Export.h>
+#include <cpPlugins/Interface/Config.h>
+
+#ifdef cpPlugins_Interface_QT4
+
+#include <map>
+#include <string>
+
+#include <QWidget>
+
+#include <vtkSmartPointer.h>
+#include <vtkImageData.h>
+#include <vtkPolyDataMapper.h>
+#include <vtkPolyDataNormals.h>
+#include <vtkQuadricLODActor.h>
+#include <vtkStripper.h>
+
+#include <cpExtensions/Visualization/MPRObjects.h>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..c8246e1
--- /dev/null
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SimpleMPRWidget</class>
+ <widget class="QWidget" name="SimpleMPRWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>424</width>
+    <height>424</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QSplitter" name="QuadSplitter">
+     <property name="minimumSize">
+      <size>
+       <width>406</width>
+       <height>406</height>
+      </size>
+     </property>
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <widget class="QSplitter" name="TopSplitter">
+      <property name="minimumSize">
+       <size>
+        <width>406</width>
+        <height>200</height>
+       </size>
+      </property>
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <widget class="QVTKWidget" name="VTK00" native="true">
+       <property name="minimumSize">
+        <size>
+         <width>200</width>
+         <height>200</height>
+        </size>
+       </property>
+      </widget>
+      <widget class="QVTKWidget" name="VTK01" native="true">
+       <property name="minimumSize">
+        <size>
+         <width>200</width>
+         <height>200</height>
+        </size>
+       </property>
+      </widget>
+     </widget>
+     <widget class="QSplitter" name="BottomSplitter">
+      <property name="minimumSize">
+       <size>
+        <width>406</width>
+        <height>200</height>
+       </size>
+      </property>
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <widget class="QVTKWidget" name="VTK10" native="true">
+       <property name="minimumSize">
+        <size>
+         <width>200</width>
+         <height>200</height>
+        </size>
+       </property>
+      </widget>
+      <widget class="QVTKWidget" name="VTK11" native="true">
+       <property name="minimumSize">
+        <size>
+         <width>200</width>
+         <height>200</height>
+        </size>
+       </property>
+      </widget>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QVTKWidget</class>
+   <extends>QWidget</extends>
+   <header location="global">QVTKWidget.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
index 9e8d4e1e7ab3d35ee94b332a7ff4fc0ee8a2816f..4e5f51a515fa1227eff9660a2987573e3148bd69 100644 (file)
@@ -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 \"" ) +
index 863d84e7d9c597ebf224efe761a6c854ff27bd76..9bad734953c89f98b01e526db4aa21ad9af13ef2 100644 (file)
@@ -1,11 +1,11 @@
 #ifndef __CPPLUGINS__INTERFACE__WORKSPACE__H__
 #define __CPPLUGINS__INTERFACE__WORKSPACE__H__
 
+#include <cpExtensions/DataStructures/Graph.h>
 #include <cpPlugins/Interface/Interface.h>
 #include <cpPlugins/Interface/DataObject.h>
 #include <cpPlugins/Interface/ProcessObject.h>
 
-#include <map>
 #include <set>
 #include <string>
 
@@ -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
index 2482a0b2ba6cbb2f8c312d25bac9d95934eb75ed..2d0392f35ebe3ea886d428ec3f4f3a7fee65475b 100644 (file)
@@ -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 (file)
index 0000000..af44e53
--- /dev/null
@@ -0,0 +1,347 @@
+#include "DoubleFloodImageFilter.h"
+#include <cpPlugins/Interface/Image.h>
+#include <cpPlugins/Interface/BaseApplication.h>
+#include <cpPlugins/Interface/Plugins.h>
+#include <cpExtensions/Interaction/ImageInteractorStyle.h>
+
+#include <vtkRenderWindowInteractor.h>
+
+#include <itkFloodFilledImageFunctionConditionalConstIterator.h>
+#include <itkImageFunction.h>
+
+#ifdef cpPlugins_Interface_QT4
+#include <QDialogButtonBox>
+
+// -------------------------------------------------------------------------
+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 (file)
index 0000000..730ffff
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef __CPPLUGINS__PLUGINS__DOUBLEFLOODIMAGEFILTER__H__
+#define __CPPLUGINS__PLUGINS__DOUBLEFLOODIMAGEFILTER__H__
+
+#include <cpPlugins/BasicFilters/cpPluginsBasicFilters_Export.h>
+#include <cpPlugins/Interface/BaseProcessObjects.h>
+
+#ifdef cpPlugins_Interface_QT4
+#include <QDialog>
+#include <QGridLayout>
+#include <QLabel>
+#include <QVBoxLayout>
+#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$