WMGridRenderer.cpp 10.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------

25
#include <cmath>
26
#include <fstream>
27
#include <iostream>
28 29
#include <string>
#include <utility>
30
#include <vector>
31

32 33 34 35
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osgText/Text>

36
#include "core/common/math/linearAlgebra/WVectorFixed.h"
37 38 39 40
#include "core/common/WAssert.h"
#include "core/common/WBoundingBox.h"
#include "core/common/WStringUtils.h"
#include "core/dataHandler/WGridRegular3D.h"
41 42
#include "core/dataHandler/WDataSetSingle.h"
#include "core/dataHandler/WDataSetFibers.h"
43
#include "core/dataHandler/WDataSetPoints.h"
44 45 46
#include "core/graphicsEngine/WGEGeodeUtils.h"
#include "core/graphicsEngine/callbacks/WGENodeMaskCallback.h"
#include "core/kernel/WKernel.h"
47 48 49 50 51
#include "WMGridRenderer.h"
#include "WMGridRenderer.xpm"
#include "WMGridRenderer_boundary.xpm"
#include "WMGridRenderer_grid.xpm"
#include "WMGridRenderer_label.xpm"
52

53
// This line is needed by the module loader to actually find your module.
54
W_LOADABLE_MODULE( WMGridRenderer )
55

56
WMGridRenderer::WMGridRenderer():
57 58
    WModule(),
    m_recompute( boost::shared_ptr< WCondition >( new WCondition() ) )
59 60 61 62 63
{
    // WARNING: initializing connectors inside the constructor will lead to an exception.
    // Implement WModule::initializeConnectors instead.
}

64
WMGridRenderer::~WMGridRenderer()
65 66 67 68 69
{
    // cleanup
    removeConnectors();
}

70
boost::shared_ptr< WModule > WMGridRenderer::factory() const
71
{
72
    return boost::shared_ptr< WModule >( new WMGridRenderer() );
73 74
}

75
const char** WMGridRenderer::getXPMIcon() const
76
{
77
    return WMGridRenderer_xpm;
78 79
}

80
const std::string WMGridRenderer::getName() const
81
{
82
    return "Grid Renderer";
83 84
}

85
const std::string WMGridRenderer::getDescription() const
86
{
87
    return "Shows the bounding box and grid of a data set.";
88 89
}

90
void WMGridRenderer::moduleMain()
91 92
{
    // use the m_input "data changed" flag
93
    m_moduleState.setResetable( true, true );
94
    m_moduleState.add( m_input->getDataChangedCondition() );
95
    m_moduleState.add( m_recompute );
96 97 98 99 100

    // signal ready state
    ready();

    // loop until the module container requests the module to quit
Alexander Wiebel committed
101
    while( !m_shutdownFlag() )
102
    {
103 104 105
        debugLog() << "Waiting for data ...";
        m_moduleState.wait();

106
        WDataSet::SPtr dataSet = m_input->getData();
107
        bool dataValid = ( dataSet != NULL );
108 109
        bool dataChanged = ( dataSet != m_dataSetOld );
        m_dataSetOld = dataSet;
110

Alexander Wiebel committed
111
        if( !dataValid )
112
        {
113
            // OK, the output has not yet sent data
114
            // NOTE: see comment at the end of this while loop for m_moduleState
115
            WGraphicsEngine::getGraphicsEngine()->getScene()->remove( m_gridNode );
116
            m_gridNode = NULL;
117 118 119
            continue;
        }

120 121
        // do nothing if these are still the same data
        if( !dataChanged )
122 123 124
        {
            continue;
        }
125

126 127 128 129
        // the grid to show
        WGridRegular3D::SPtr regGrid;

        // is this a DS with a regular grid?
130
        WDataSetSingle::SPtr dsSingle = boost::dynamic_pointer_cast< WDataSetSingle >( dataSet );
131 132
        if( dsSingle )
        {
133
            regGrid = boost::dynamic_pointer_cast< WGridRegular3D >( dsSingle->getGrid() );
134 135 136
        }

        // is this a fiber dataset?
137
        WDataSetFibers::SPtr dsFibers = boost::dynamic_pointer_cast< WDataSetFibers >( dataSet );
138 139 140 141 142 143
        if( dsFibers )
        {
            debugLog() << "Fiber Data.";

            WBoundingBox bb = dsFibers->getBoundingBox();
            // this basically is a fake but we need a grid for WGEGridNode. So we construct one using the BBox
Sebastian Eichelbaum committed
144
            WGridTransformOrtho gridTransform( bb.xMax() - bb.xMin(), bb.yMax() - bb.yMin(), bb.zMax() - bb.zMin() );
145 146 147 148 149
            gridTransform.translate( WVector3d( bb.xMin(), bb.yMin(), bb.zMin() ) );
            regGrid = WGridRegular3D::SPtr( new WGridRegular3D( 2, 2, 2, gridTransform ) );
        }

        // is this a point dataset?
150
        WDataSetPoints::SPtr dsPoints = boost::dynamic_pointer_cast< WDataSetPoints >( dataSet );
151 152 153 154 155 156 157
        if( dsPoints )
        {
            debugLog() << "Points Data.";

            WBoundingBox bb = dsPoints->getBoundingBox();

            // this basically is a fake but we need a grid for WGEGridNode. So we construct one using the BBox
158 159 160 161
            const double makeFakeNonZero = 0.000001;
            WGridTransformOrtho gridTransform( bb.xMax() - bb.xMin() + makeFakeNonZero,
                                               bb.yMax() - bb.yMin() + makeFakeNonZero,
                                               bb.zMax() - bb.zMin() + makeFakeNonZero );
Sebastian Eichelbaum committed
162 163
            gridTransform.translate( WVector3d( bb.xMin(), bb.yMin(), bb.zMin() ) );
            regGrid = WGridRegular3D::SPtr( new WGridRegular3D( 2, 2, 2, gridTransform ) );
164 165
        }

166
        // create the new grid node if it not exists
167
        if( !m_gridNode && regGrid )
168
        {
169
            debugLog() << "Creating grid geode.";
170 171 172 173
            m_gridNode = new WGEGridNode( regGrid );
            m_gridNode->addUpdateCallback( new WGENodeMaskCallback( m_active ) );
            WGraphicsEngine::getGraphicsEngine()->getScene()->insert( m_gridNode );
        }
174 175 176 177 178 179 180
        else if( m_gridNode && !regGrid )
        {
            debugLog() << "Removing grid geode.";
            // there is a grid node which needs to be removed as we do NOT have a valid regular grid.
            WGraphicsEngine::getGraphicsEngine()->getScene()->remove( m_gridNode );
            m_gridNode = NULL;
        }
181

182 183
        m_gridNode->setBBoxColor( *m_bboxColor );
        m_gridNode->setGridColor( *m_gridColor );
184 185
        m_gridNode->setGridLineWidth( m_gridLineWidth->get() );
        m_gridNode->setBoxLineWidth( m_boxLineWidth->get() );
186
        updateNode( m_mode );
187
        m_gridNode->setGrid( regGrid );
188
    }
189

190
    WGraphicsEngine::getGraphicsEngine()->getScene()->remove( m_gridNode );
191 192
}

193
void WMGridRenderer::connectors()
194 195
{
    // initialize connectors
196 197 198
    m_input = boost::shared_ptr< WModuleInputData < WDataSet  > >(
        new WModuleInputData< WDataSet >( shared_from_this(),
                                                               "in", "The dataset to show" )
199 200 201 202 203 204 205 206 207
        );

    // add it to the list of connectors. Please note, that a connector NOT added via addConnector will not work as expected.
    addConnector( m_input );

    // call WModules initialization
    WModule::connectors();
}

208
void WMGridRenderer::properties()
209
{
210
    WPropertyBase::PropertyChangeNotifierType  notifier = boost::bind( &WMGridRenderer::updateNode, this, _1 );
211

212
    m_bboxColor = m_properties->addProperty( "Bounding box color", "The color of the bounding box.", WColor( 0.3, 0.3, 0.3, 1.0 ), notifier );
213 214 215
    m_boxLineWidth = m_properties->addProperty( "Bounding box line width", "The width of the grid lines.", 4, notifier );
    m_boxLineWidth->setMin( 1 );
    m_boxLineWidth->setMax( 10 );
216

217
    m_gridColor = m_properties->addProperty( "Grid color", "The color of the grid.", WColor( 0.1, 0.1, 0.1, 1.0 ), notifier );
218 219 220
    m_gridLineWidth = m_properties->addProperty( "Grid line width", "The width of the grid lines.", 1, notifier );
    m_gridLineWidth->setMin( 1 );
    m_gridLineWidth->setMax( 10 );
221 222

    m_possibleModes = WItemSelection::SPtr( new WItemSelection() );
223
    m_possibleModes->addItem( "Labels", "Show the boundary labels.", WMGridRenderer_label_xpm );          // NOTE: you can add XPM images here.
224
    m_possibleModes->addItem( "Bounding box", "Show the bounding box.", WMGridRenderer_boundary_xpm );
225
    m_possibleModes->addItem( "Grid", "Show the inner grid.",  WMGridRenderer_grid_xpm );
226 227 228 229 230 231

    // selecting all at once might be a bad idea since the grid rendering can be very very slow. So, by default, only show bbox and labels.
    WItemSelector sel = m_possibleModes->getSelectorFirst();
    m_mode = m_properties->addProperty( "Mode", "What should be rendered.",  sel.newSelector( 1 ), notifier );
    WPropertyHelper::PC_NOTEMPTY::addTo( m_mode );

232
    WModule::properties();
233
}
234

235
void WMGridRenderer::updateNode( WPropertyBase::SPtr property )
236 237
{
    // only update if there is a grid node
238
    if( !m_gridNode )
239 240 241 242 243
    {
        return;
    }

    // color of bbox changed
244
    if( property == m_bboxColor )
245 246 247 248 249
    {
        m_gridNode->setBBoxColor( *m_bboxColor );
    }

    // color of grid changed
250
    if( property == m_gridColor )
251 252 253 254
    {
        m_gridNode->setGridColor( *m_gridColor );
    }

255 256 257 258 259 260 261 262 263 264
    if( property == m_gridLineWidth )
    {
        m_gridNode->setGridLineWidth( m_gridLineWidth->get() );
    }

    if( property == m_boxLineWidth )
    {
        m_gridNode->setBoxLineWidth( m_boxLineWidth->get() );
    }

265
    // mode changed
266
    if( property == m_mode )
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
    {
        WItemSelector s = m_mode->get( true );

        bool labels = false;
        bool bbox = false;
        bool grid = false;

        // The multi property allows the selection of several items. So, iteration needs to be done here:
        for( size_t i = 0; i < s.size(); ++i )
        {
            size_t idx = s.getItemIndexOfSelected( i );

            // check what was selected
            labels = labels || ( idx == 0 );
            bbox = bbox || ( idx == 1 );
            grid = grid || ( idx == 2 );
        }

        m_gridNode->setEnableLabels( labels );
        m_gridNode->setEnableGrid( grid );
        m_gridNode->setEnableBBox( bbox );
    }
}