OpenWalnut  1.5.0dev
WMArbitraryPlane.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <memory>
26 #include <string>
27 #include <vector>
28 
29 #include <osg/Geometry>
30 
31 #include "WMArbitraryPlane.h"
32 #include "WMArbitraryPlane.xpm"
33 #include "core/dataHandler/WDataHandler.h"
34 #include "core/dataHandler/WDataSet.h"
35 #include "core/dataHandler/WDataSetScalar.h"
36 #include "core/dataHandler/WDataSetSingle.h"
37 #include "core/dataHandler/WGridRegular3D.h"
38 #include "core/dataHandler/WSubject.h"
39 #include "core/dataHandler/WValueSet.h"
40 #include "core/graphicsEngine/WGEColormapping.h"
41 #include "core/graphicsEngine/WGEUtils.h"
42 #include "core/graphicsEngine/shaders/WGEPropertyUniform.h"
43 #include "core/graphicsEngine/shaders/WGEShader.h"
44 #include "core/kernel/WKernel.h"
45 #include "core/kernel/WSelectionManager.h"
46 
47 // This line is needed by the module loader to actually find your module. Do not remove. Do NOT add a ";" here.
48 W_LOADABLE_MODULE( WMArbitraryPlane )
49 
51  WModule(),
52  m_dirty( false )
53 {
54  // initialize members
55 }
56 
58 {
59  // Cleanup!
60 }
61 
62 std::shared_ptr< WModule > WMArbitraryPlane::factory() const
63 {
64  // See "src/modules/template/" for an extensively documented example.
65  return std::shared_ptr< WModule >( new WMArbitraryPlane() );
66 }
67 
68 const char** WMArbitraryPlane::getXPMIcon() const
69 {
70  return arbitraryPlane_xpm;
71 }
72 
73 const std::string WMArbitraryPlane::getName() const
74 {
75  // Specify your module name here. This name must be UNIQUE!
76  return "Arbitrary Plane";
77 }
78 
79 const std::string WMArbitraryPlane::getDescription() const
80 {
81  return "Module draws an arbitrarily moveable plane through the data.";
82 }
83 
85 {
86  // Put the code for your connectors here. See "src/modules/template/" for an extensively documented example.
87 
88  // call WModules initialization
90 }
91 
93 {
94  // Initialize the properties
95  m_propCondition = std::shared_ptr< WCondition >( new WCondition() );
96 
97  m_showComplete = m_properties->addProperty( "Show complete", "Slice should be drawn complete even if the texture value is zero.",
98  false, m_propCondition );
99  m_showManipulators = m_properties->addProperty( "Show manipulators", "Hide/Show manipulators.", true, m_propCondition );
100 
101  m_attach2Crosshair = m_properties->addProperty( "Attach to crosshair", "Attach to Crosshair", true, m_propCondition );
102 
103  m_buttonReset2Axial = m_properties->addProperty( "Axial", "Resets and aligns the plane", WPVBaseTypes::PV_TRIGGER_READY, m_propCondition );
104  m_buttonReset2Coronal = m_properties->addProperty( "Coronal", "Resets and aligns the plane", WPVBaseTypes::PV_TRIGGER_READY, m_propCondition );
105  m_buttonReset2Sagittal = m_properties->addProperty( "Sagittal", "Resets and aligns the plane", WPVBaseTypes::PV_TRIGGER_READY, m_propCondition );
106 
108 }
109 
111 {
112  initPlane();
113 
114  updatePlane();
115 
116  ready();
117 
118  m_moduleState.setResetable( true, true );
120  m_moduleState.add( m_active->getUpdateCondition() );
121 
122  while( !m_shutdownFlag() )
123  {
125 
126  if( m_shutdownFlag() )
127  {
128  break;
129  }
130 
131  if( m_showComplete->changed() )
132  {
133  m_showComplete->get( true );
134  m_dirty = true;
135  }
136 
137  if( m_active->changed() )
138  {
139  if( m_active->get( true ) && m_showManipulators->get() )
140  {
141  m_s0->unhide();
142  m_s1->unhide();
143  m_s2->unhide();
144  }
145  else
146  {
147  m_s0->hide();
148  m_s1->hide();
149  m_s2->hide();
150  }
151  }
152 
153  if( m_showManipulators->changed() )
154  {
155  if( m_showManipulators->get( true ) )
156  {
157  if( m_active->get() )
158  {
159  m_s0->unhide();
160  m_s1->unhide();
161  m_s2->unhide();
162  }
163  }
164  else
165  {
166  m_s0->hide();
167  m_s1->hide();
168  m_s2->hide();
169  }
170  }
171 
173  {
174  WPosition center = WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->getPosition();
175  m_s0->setPosition( center );
176  m_s1->setPosition( WPosition( center[0] - 100, center[1], center[2] ) );
177  m_s2->setPosition( WPosition( center[0], center[1] - 100, center[2] ) );
179  m_dirty = true;
180  }
181 
183  {
184  WPosition center = WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->getPosition();
185  m_s0->setPosition( center );
186  m_s1->setPosition( WPosition( center[0] - 100, center[1], center[2] ) );
187  m_s2->setPosition( WPosition( center[0], center[1], center[2] - 100 ) );
189  m_dirty = true;
190  }
191 
193  {
194  WPosition center = WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->getPosition();
195  m_s0->setPosition( center );
196  m_s1->setPosition( WPosition( center[0], center[1], center[2] - 100 ) );
197  m_s2->setPosition( WPosition( center[0], center[1] - 100, center[2] ) );
199  m_dirty = true;
200  }
201  }
202  WGraphicsEngine::getGraphicsEngine()->getScene()->remove( &( *m_s0 ) );
203  WGraphicsEngine::getGraphicsEngine()->getScene()->remove( &( *m_s1 ) );
204  WGraphicsEngine::getGraphicsEngine()->getScene()->remove( &( *m_s2 ) );
205 
206  m_s0->removeROIChangeNotifier( m_changeRoiSignal );
207  m_s1->removeROIChangeNotifier( m_changeRoiSignal );
208  m_s2->removeROIChangeNotifier( m_changeRoiSignal );
209 
210  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_rootNode );
211 }
212 
214 {
216  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_rootNode );
217  m_geode = new osg::Geode();
218  m_geode->setName( "_arbitraryPlane" );
219 
220  // create shader
221  m_shader = osg::ref_ptr< WGEShader > ( new WGEShader( "WMArbitraryPlane", m_localPath ) );
222  m_shader->apply( m_rootNode );
223 
224  // Apply colormapping
226 
227  // bind some uniforms with properties
228  m_geode->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropBool >( "u_showComplete", m_showComplete ) );
229 
230  // we need transparency
231  m_geode->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
232  m_geode->getOrCreateStateSet()->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
233 
234  m_rootNode->insert( m_geode );
235  m_rootNode->addUpdateCallback( new WGEFunctorCallback< osg::Node >( boost::bind( &WMArbitraryPlane::updateCallback, this ) ) );
236 
237  WPosition center = WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->getPosition();
238  m_p0 = WPosition( center );
239  m_p1 = WPosition( center[0] - 100, center[1], center[2] );
240  m_p2 = WPosition( center[0], center[1] - 100, center[2] );
241 
242  m_s0 = osg::ref_ptr<WROISphere>( new WROISphere( m_p0, 2.5 ) );
243  m_s1 = osg::ref_ptr<WROISphere>( new WROISphere( m_p1, 2.5 ) );
244  m_s1->setLockY();
245  m_s2 = osg::ref_ptr<WROISphere>( new WROISphere( m_p2, 2.5 ) );
246  m_s2->setLockX();
247 
248  WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( &( *m_s0 ) );
249  WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( &( *m_s1 ) );
250  WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( &( *m_s2 ) );
251 
253  = std::shared_ptr< boost::function< void() > >( new boost::function< void() >( boost::bind( &WMArbitraryPlane::setDirty, this ) ) );
254  m_s0->addROIChangeNotifier( m_changeRoiSignal );
255  m_s1->addROIChangeNotifier( m_changeRoiSignal );
256  m_s2->addROIChangeNotifier( m_changeRoiSignal );
257 }
258 
260 {
261  m_geode->removeDrawables( 0, 1 );
262 
263  if( m_attach2Crosshair->get() )
264  {
265  m_s0->setPosition( WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->getPosition() );
266  }
267 
268  WPosition p0 = m_s0->getPosition();
269 
270  if( p0 != m_p0 )
271  {
272  WVector3d offset = p0 - m_p0;
273  m_p0 = p0;
274  m_s1->setPosition( m_s1->getPosition() + offset );
275  m_s2->setPosition( m_s2->getPosition() + offset );
276  }
277  WPosition p1 = m_s1->getPosition();
278  WPosition p2 = m_s2->getPosition();
279 
280  WPosition v0( p1[0] , p2[1] , p0[2] - ( p0[2] - p1[2] ) - ( p0[2] - p2[2] ) );
281  WPosition v1( p1[0] , p0[1] + p0[1] - p2[1] , p0[2] - ( p0[2] - p1[2] ) + ( p0[2] - p2[2] ) );
282  WPosition v2( p0[0] + p0[0] - p1[0] , p0[1] + p0[1] - p2[1] , p0[2] + ( p0[2] - p1[2] ) + ( p0[2] - p2[2] ) );
283  WPosition v3( p0[0] + p0[0] - p1[0] , p2[1] , p0[2] + ( p0[2] - p1[2] ) - ( p0[2] - p2[2] ) );
284 
285  osg::ref_ptr<osg::Geometry> planeGeometry = osg::ref_ptr<osg::Geometry>( new osg::Geometry() );
286  osg::Vec3Array* planeVertices = new osg::Vec3Array;
287 
288  planeVertices->push_back( v0 );
289  planeVertices->push_back( v1 );
290  planeVertices->push_back( v2 );
291  planeVertices->push_back( v3 );
292 
293  planeGeometry->setVertexArray( planeVertices );
294  osg::DrawElementsUInt* quad = new osg::DrawElementsUInt( osg::PrimitiveSet::QUADS, 0 );
295  quad->push_back( 3 );
296  quad->push_back( 2 );
297  quad->push_back( 1 );
298  quad->push_back( 0 );
299  planeGeometry->addPrimitiveSet( quad );
300 
301  m_geode->addDrawable( planeGeometry );
302 
303  m_dirty = false;
304 }
305 
307 {
308  WPosition ch = WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->getPosition();
310  if( ch[0] != cho[0] || ch[1] != cho[1] || ch[2] != cho[2] )
311  {
312  setDirty();
313  }
314 
315  if( isDirty() )
316  {
317  updatePlane();
318  }
319 }
320 
322 {
323  m_dirty = true;
324 }
325 
327 {
328  return m_dirty;
329 }
330 
332 {
333  return m_s0->getPosition();
334 }
virtual void wait() const
Wait for the condition.
void setResetable(bool resetable=true, bool autoReset=true)
Sets the resetable flag.
virtual void add(std::shared_ptr< WCondition > condition)
Adds another condition to the set of conditions to wait for.
Class to encapsulate boost::condition_variable_any.
Definition: WCondition.h:42
static void apply(osg::ref_ptr< osg::Node > node, WMatrix4d preTransform=WMatrix4d::identity(), osg::ref_ptr< WGEShader > shader=osg::ref_ptr< WGEShader >(), size_t startTexUnit=0)
Apply the colormapping to the specified node.
This callback allows you a simple usage of callbacks in your module.
This class adds some convenience methods to WGEGroupNode.
Class implementing a uniform which can be controlled by a property instance.
Class encapsulating the OSG Program class for a more convenient way of adding and modifying shader.
Definition: WGEShader.h:48
static std::shared_ptr< WGraphicsEngine > getGraphicsEngine()
Returns instance of the graphics engine.
std::shared_ptr< WSelectionManager > getSelectionManager()
get for selection manager
Definition: WKernel.cpp:214
static WKernel * getRunningKernel()
Returns pointer to the currently running kernel.
Definition: WKernel.cpp:117
std::shared_ptr< WGraphicsEngine > getGraphicsEngine() const
Returns pointer to currently running instance of graphics engine.
Definition: WKernel.cpp:122
Arbitrarily orientable cutting plane through the data.
osg::ref_ptr< WROISphere > m_s2
stores pointer to manipulator 2
WPosition m_p2
stores the last position of manipulator 2
bool m_dirty
dirty flag, used when manipulator positions change
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
virtual ~WMArbitraryPlane()
destructor
virtual const std::string getName() const
Gives back the name of this module.
WPropTrigger m_buttonReset2Axial
When triggered the center manipulator is set to the nav slice position and the plane is aligned along...
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
virtual void moduleMain()
Entry point after loading the module.
virtual const std::string getDescription() const
Gives back a description of this module.
void updateCallback()
update function, called with each update pass of the osg render loop
osg::ref_ptr< WGEShader > m_shader
the shader object for this module
virtual void properties()
Initialize the properties for this module.
osg::ref_ptr< osg::Geode > m_geode
The geometry rendered by this module.
osg::ref_ptr< WROISphere > m_s0
stores pointer to the center manipulator
WPropBool m_attach2Crosshair
If true the center position will move with the nav slice selection.
virtual std::shared_ptr< WModule > factory() const
Due to the prototype design pattern used to build modules, this method returns a new instance of this...
void initPlane()
called once at the start of the module main loop
WPropTrigger m_buttonReset2Sagittal
When triggered the center manipulator is set to the nav slice position and the plane is aligned along...
WPosition m_p1
stores the last position of manipulator 1
virtual void connectors()
Initialize the connectors this module is using.
WPosition getCenterPosition()
getter for the position of the center manipulator
WPropBool m_showManipulators
True if the manipulator spheres should be shown.
std::shared_ptr< boost::function< void() > > m_changeRoiSignal
Signal that can be used to update the plane.
osg::ref_ptr< WROISphere > m_s1
stores pointer to manipulator 1
WPropTrigger m_buttonReset2Coronal
When triggered the center manipulator is set to the nav slice position and the plane is aligned along...
void updatePlane()
updates the plane with the current settings
WPosition m_p0
stores the last position of the center manipulator
WPropBool m_showComplete
True if the shader shouldn't discard a fragment when the value is zero.
WMArbitraryPlane()
standard constructor
void setDirty()
setter for dirty flag
osg::ref_ptr< WGEManagedGroupNode > m_rootNode
The root node used for this modules graphics.
Class representing a single module of OpenWalnut.
Definition: WModule.h:72
boost::filesystem::path m_localPath
The path where the module binary resides in.
Definition: WModule.h:734
virtual void properties()
Initialize properties in this function.
Definition: WModule.cpp:212
std::shared_ptr< WProperties > m_properties
The property object for the module.
Definition: WModule.h:640
void ready()
Call this whenever your module is ready and can react on property changes.
Definition: WModule.cpp:505
WConditionSet m_moduleState
The internal state of the module.
Definition: WModule.h:703
WPropBool m_active
True whenever the module should be active.
Definition: WModule.h:723
virtual void connectors()
Initialize connectors in this function.
Definition: WModule.cpp:208
This only is a 3d double vector.
A sphere representing a region of interest.
Definition: WROISphere.h:44
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.
@ PV_TRIGGER_TRIGGERED
Trigger property: got triggered.
@ PV_TRIGGER_READY
Trigger property: is ready to be triggered (again)