OpenWalnut  1.5.0dev
WMArbitraryROIs.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/Geode>
30 #include <osg/Geometry>
31 #include <osg/LightModel>
32 #include <osg/Material>
33 #include <osg/PolygonMode>
34 #include <osg/StateAttribute>
35 #include <osg/StateSet>
36 
37 #include "WMArbitraryROIs.h"
38 #include "WMArbitraryROIs.xpm"
39 #include "core/common/WAssert.h"
40 #include "core/common/algorithms/WMarchingLegoAlgorithm.h"
41 #include "core/dataHandler/WDataSetScalar.h"
42 #include "core/graphicsEngine/WROIArbitrary.h"
43 #include "core/graphicsEngine/WROIBox.h"
44 #include "core/kernel/WKernel.h"
45 #include "core/kernel/WROIManager.h"
46 #include "core/kernel/WSelectionManager.h"
47 
48 // This line is needed by the module loader to actually find your module.
49 W_LOADABLE_MODULE( WMArbitraryROIs )
50 
51 WMArbitraryROIs::WMArbitraryROIs():
52  WModule(),
53  m_recompute( std::shared_ptr< WCondition >( new WCondition() ) ),
54  m_dataSet(),
55  m_moduleNode( new WGEGroupNode() ),
56  m_showSelector( true )
57 {
58 }
59 
60 WMArbitraryROIs::~WMArbitraryROIs()
61 {
62  // Cleanup!
63 }
64 
65 std::shared_ptr< WModule > WMArbitraryROIs::factory() const
66 {
67  // See "src/modules/template/" for an extensively documented example.
68  return std::shared_ptr< WModule >( new WMArbitraryROIs() );
69 }
70 
71 const char** WMArbitraryROIs::getXPMIcon() const
72 {
73  return arbitraryROI_xpm;
74 }
75 
76 const std::string WMArbitraryROIs::getName() const
77 {
78  // Specify your module name here. This name must be UNIQUE!
79  return "Arbitrary ROIs";
80 }
81 
82 const std::string WMArbitraryROIs::getDescription() const
83 {
84  return "Create non uniformly shaped ROIs for fiber selection. The ROI "
85  "is what is enclosed by a surface created as isosurface from "
86  "the data within a ROI box.";
87 }
88 
90 {
91  // initialize connectors
92  m_input = std::shared_ptr< WModuleInputData < WDataSetScalar > >(
93  new WModuleInputData< WDataSetScalar >( shared_from_this(), "in", "Dataset to cut ROI from." ) );
94  // add it to the list of connectors. Please note, that a connector NOT added via addConnector will not work as expected.
96 
97  // call WModules initialization
99 }
100 
102 {
103  m_propCondition = std::shared_ptr< WCondition >( new WCondition() );
104 
105  m_finalizeTrigger = m_properties->addProperty( "Finalize", "Finalize and add to ROI manager", WPVBaseTypes::PV_TRIGGER_READY, m_propCondition );
106  m_threshold = m_properties->addProperty( "Threshold", "", 1.0, m_propCondition );
107  m_surfaceColor = m_properties->addProperty( "Surface color", "", WColor( 1.0, 0.3, 0.3, 1.0 ), m_propCondition );
108 
110 }
111 
113 {
114  // use the m_input "data changed" flag
115  m_moduleState.setResetable( true, true );
117  m_moduleState.add( m_input->getDataChangedCondition() );
119 
120  // signal ready state
121  ready();
122 
123  // init the intial ROI position using the current crosshair position
124  WPosition crossHairPos = WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->getPosition();
125  m_lastMinPos = crossHairPos - WPosition( 10., 10., 10. );
126  m_lastMaxPos = crossHairPos + WPosition( 10., 10., 10. );
127 
128  // loop until the module container requests the module to quit
129  while( !m_shutdownFlag() )
130  {
131  m_moduleState.wait(); // waits for firing of m_moduleState ( dataChanged, shutdown, etc. )
132 
133  if( m_shutdownFlag() )
134  {
135  break;
136  }
137 
138  if( m_input->getData() && m_dataSet != m_input->getData() )
139  {
140  // remove old ROI and ISO
141  cleanup();
142 
143  // acquire data from the input connector
144  m_dataSet = m_input->getData();
145 
146  m_threshold->setMin( m_dataSet->getMin() );
147  m_threshold->setMax( m_dataSet->getMax() );
148  m_threshold->set( ( m_dataSet->getMax() - m_dataSet->getMin() ) / 2.0 );
149 
151  }
152 
153  if( m_threshold->changed() )
154  {
155  m_threshold->get( true );
156  m_showSelector = true;
158  renderMesh();
159  }
160 
162  {
163  m_showSelector = false;
165  renderMesh();
166  finalizeROI();
168  }
169  }
170  cleanup();
171 }
172 
174 {
175  // if we already had a ROI, we want to keep the position for the next ROI
176  if( m_selectionROI )
177  {
178  m_lastMinPos = m_selectionROI->getMinPos();
179  m_lastMaxPos = m_selectionROI->getMaxPos();
180  }
181  m_moduleNode->clear();
182  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_moduleNode );
183  if( m_selectionROI )
184  {
185  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_selectionROI );
186  }
187 }
188 
190 {
191  m_selectionROI = osg::ref_ptr< WROIBox >( new WROIBox( m_lastMinPos, m_lastMaxPos ) );
192  m_selectionROI->setColor( osg::Vec4( 0., 0., 1.0, 0.4 ) );
194 }
195 
197 {
198  if( !m_active->get() )
199  {
200  return;
201  }
202 
203  std::shared_ptr< WValueSetBase > newValueSet;
204 
205  std::shared_ptr< WGridRegular3D > grid = std::dynamic_pointer_cast< WGridRegular3D >( m_dataSet->getGrid() );
206 
207  size_t order = ( *m_dataSet ).getValueSet()->order();
208  size_t vDim = ( *m_dataSet ).getValueSet()->dimension();
209 
210  float threshold = m_threshold->get();
211  std::shared_ptr< std::vector< float > > data( new std::vector< float >() );
212 
213  switch( ( *m_dataSet ).getValueSet()->getDataType() )
214  {
215  case W_DT_UNSIGNED_CHAR:
216  {
217  std::shared_ptr< WValueSet< unsigned char > > vals;
218  vals = std::dynamic_pointer_cast< WValueSet< unsigned char > >( ( *m_dataSet ).getValueSet() );
219  WAssert( vals, "Data type and data type indicator must fit." );
220  data = cutArea( ( *m_dataSet ).getGrid(), vals );
221  break;
222  }
223  case W_DT_INT16:
224  {
225  std::shared_ptr< WValueSet< int16_t > > vals;
226  vals = std::dynamic_pointer_cast< WValueSet< int16_t > >( ( *m_dataSet ).getValueSet() );
227  WAssert( vals, "Data type and data type indicator must fit." );
228  data = cutArea( ( *m_dataSet ).getGrid(), vals );
229  break;
230  }
231  case W_DT_SIGNED_INT:
232  {
233  std::shared_ptr< WValueSet< int32_t > > vals;
234  vals = std::dynamic_pointer_cast< WValueSet< int32_t > >( ( *m_dataSet ).getValueSet() );
235  WAssert( vals, "Data type and data type indicator must fit." );
236  cutArea( ( *m_dataSet ).getGrid(), vals );
237  data = cutArea( ( *m_dataSet ).getGrid(), vals );
238  break;
239  }
240  case W_DT_FLOAT:
241  {
242  std::shared_ptr< WValueSet< float > > vals;
243  vals = std::dynamic_pointer_cast< WValueSet< float > >( ( *m_dataSet ).getValueSet() );
244  WAssert( vals, "Data type and data type indicator must fit." );
245  data = cutArea( ( *m_dataSet ).getGrid(), vals );
246  break;
247  }
248  case W_DT_DOUBLE:
249  {
250  std::shared_ptr< WValueSet< double > > vals;
251  vals = std::dynamic_pointer_cast< WValueSet< double > >( ( *m_dataSet ).getValueSet() );
252  WAssert( vals, "Data type and data type indicator must fit." );
253  data = cutArea( ( *m_dataSet ).getGrid(), vals );
254  break;
255  }
256  default:
257  WAssert( false, "Unknown data type in ArbitraryROIs module" );
258  }
259  m_newValueSet = std::shared_ptr< WValueSet< float > >( new WValueSet< float >( order, vDim, data, W_DT_FLOAT ) );
260  WMarchingLegoAlgorithm mlAlgo;
261  m_triMesh = mlAlgo.generateSurface( grid->getNbCoordsX(), grid->getNbCoordsY(), grid->getNbCoordsZ(),
262  grid->getTransformationMatrix(),
263  m_newValueSet->rawDataVectorPointer(),
264  threshold );
265 }
266 
267 template< typename T >
268 std::shared_ptr< std::vector< float > > WMArbitraryROIs::cutArea( std::shared_ptr< WGrid > inGrid, std::shared_ptr< WValueSet< T > > vals )
269 {
270  std::shared_ptr< WGridRegular3D > grid = std::dynamic_pointer_cast< WGridRegular3D >( inGrid );
271 
272  size_t nx = grid->getNbCoordsX();
273  size_t ny = grid->getNbCoordsY();
274  size_t nz = grid->getNbCoordsZ();
275 
276  double dx = grid->getOffsetX();
277  double dy = grid->getOffsetY();
278  double dz = grid->getOffsetZ();
279 
280  size_t xMin = static_cast<size_t>( m_selectionROI->getMinPos()[0] / dx );
281  size_t yMin = static_cast<size_t>( m_selectionROI->getMinPos()[1] / dy );
282  size_t zMin = static_cast<size_t>( m_selectionROI->getMinPos()[2] / dz );
283  size_t xMax = static_cast<size_t>( m_selectionROI->getMaxPos()[0] / dx );
284  size_t yMax = static_cast<size_t>( m_selectionROI->getMaxPos()[1] / dy );
285  size_t zMax = static_cast<size_t>( m_selectionROI->getMaxPos()[2] / dz );
286 
287  std::shared_ptr< std::vector< float > > newVals( new std::vector< float >( nx * ny * nz, 0 ) );
288 
289  size_t x, y, z;
290  for( z = 0; z < nz; ++z )
291  {
292  for( y = 0 ; y < ny; ++y )
293  {
294  for( x = 0 ; x < nx; ++x )
295  {
296  if( ( x > xMin ) && ( x < xMax ) && ( y > yMin ) && ( y < yMax ) && ( z > zMin ) && ( z < zMax ) )
297  {
298  ( *newVals )[ x + nx * y + nx * ny * z ] = static_cast< float >( vals->getScalar( x + nx * y + nx * ny * z ) );
299  }
300  }
301  }
302  }
303  return newVals;
304 }
305 
307 {
308  m_moduleNode->remove( m_outputGeode );
309 
310  if( m_showSelector )
311  {
312  osg::Geometry* surfaceGeometry = new osg::Geometry();
313  m_outputGeode = osg::ref_ptr< osg::Geode >( new osg::Geode );
314 
315  m_outputGeode->setName( "ROI" );
316 
317  surfaceGeometry->setVertexArray( m_triMesh->getVertexArray() );
318 
319  // ------------------------------------------------
320  // normals
321  surfaceGeometry->setNormalArray( m_triMesh->getVertexNormalArray() );
322  surfaceGeometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
323 
324  // ------------------------------------------------
325  // colors
326  osg::Vec4Array* colors = new osg::Vec4Array;
327  colors->push_back( osg::Vec4( 0.2f, 1.0f, 0.2f, 1.0f ) );
328  surfaceGeometry->setColorArray( colors );
329  surfaceGeometry->setColorBinding( osg::Geometry::BIND_OVERALL );
330 
331  osg::DrawElementsUInt* surfaceElement = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, 0 );
332 
333  std::vector< size_t >tris = m_triMesh->getTriangles();
334  surfaceElement->reserve( tris.size() );
335 
336  for( unsigned int vertId = 0; vertId < tris.size(); ++vertId )
337  {
338  surfaceElement->push_back( tris[vertId] );
339  }
340  surfaceGeometry->addPrimitiveSet( surfaceElement );
341  m_outputGeode->addDrawable( surfaceGeometry );
342 
343  osg::StateSet* state = m_outputGeode->getOrCreateStateSet();
344  osg::ref_ptr<osg::LightModel> lightModel = new osg::LightModel();
345  lightModel->setTwoSided( true );
346  state->setAttributeAndModes( lightModel.get(), osg::StateAttribute::ON );
347  state->setMode( GL_BLEND, osg::StateAttribute::ON );
348 
349  // {
350  // osg::ref_ptr< osg::Material > material = new osg::Material();
351  // material->setDiffuse( osg::Material::FRONT, osg::Vec4( 1.0, 1.0, 1.0, 1.0 ) );
352  // material->setSpecular( osg::Material::FRONT, osg::Vec4( 0.0, 0.0, 0.0, 1.0 ) );
353  // material->setAmbient( osg::Material::FRONT, osg::Vec4( 0.1, 0.1, 0.1, 1.0 ) );
354  // material->setEmission( osg::Material::FRONT, osg::Vec4( 0.0, 0.0, 0.0, 1.0 ) );
355  // material->setShininess( osg::Material::FRONT, 25.0 );
356  // state->setAttribute( material );
357  // }
358 
359  m_moduleNode->insert( m_outputGeode );
360  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_moduleNode );
361  }
362 }
363 
365 {
366  if( !m_active->get() )
367  {
368  return;
369  }
370 
371  std::shared_ptr< WGridRegular3D > grid = std::dynamic_pointer_cast< WGridRegular3D >( m_dataSet->getGrid() );
372  osg::ref_ptr< WROI > newROI = osg::ref_ptr< WROI >( new WROIArbitrary( grid->getNbCoordsX(), grid->getNbCoordsY(), grid->getNbCoordsZ(),
373  grid->getTransformationMatrix(),
374  *m_newValueSet->rawDataVectorPointer(),
375  m_triMesh,
376  m_threshold->get(),
377  m_dataSet->getMax(), m_surfaceColor->get( true ) ) );
378 
379  if( WKernel::getRunningKernel()->getRoiManager()->getSelectedRoi() == NULL )
380  {
381  WKernel::getRunningKernel()->getRoiManager()->addRoi( newROI );
382  }
383  else
384  {
385  WKernel::getRunningKernel()->getRoiManager()->addRoi( newROI, WKernel::getRunningKernel()->getRoiManager()->getSelectedRoi() );
386  }
387 }
388 
390 {
391  if( m_selectionROI )
392  {
393  if( m_active->get() )
394  {
395  m_selectionROI->setNodeMask( 0xFFFFFFFF );
396  }
397  else
398  {
399  m_selectionROI->setNodeMask( 0x0 );
400  }
401  }
402 
404 }
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
Class to wrap around the osg Group node and providing a thread safe add/removal mechanism.
Definition: WGEGroupNode.h:48
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< WROIManager > getRoiManager()
get for roi manager
Definition: WKernel.cpp:209
std::shared_ptr< WGraphicsEngine > getGraphicsEngine() const
Returns pointer to currently running instance of graphics engine.
Definition: WKernel.cpp:122
Create non uniformly shaped ROIs for fiber selection.
virtual void activate()
Callback for m_active.
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
std::shared_ptr< WModuleInputData< WDataSetScalar > > m_input
Input connector required by this module.
void initSelectionROI()
create a selection box to mark the area in a dataset which will provide the data for a new ROI
void finalizeROI()
creates a ROI and adds it to the ROI manager
virtual void moduleMain()
Entry point after loading the module.
virtual const std::string getDescription() const
Gives back a description of this module.
osg::ref_ptr< WROIBox > m_selectionROI
stores a pointer to the cutting tool ROI
std::shared_ptr< WCondition > m_recompute
This condition denotes whether we need to recompute the surface.
WPosition m_lastMaxPos
the last know max position of the ROI if there was any
virtual const std::string getName() const
Gives back the name of this module.
osg::ref_ptr< osg::Geode > m_outputGeode
Pointer to geode containing the glpyhs.
void renderMesh()
renders the temporary ROI
virtual void connectors()
Initialize the connectors this module is using.
WPropColor m_surfaceColor
Property determining the color for the surface.
void cleanup()
Removes the ROI and cleans up the scene.
WPropDouble m_threshold
the threshold for the ROI
std::shared_ptr< const WDataSetScalar > m_dataSet
pointer to dataSet to be able to access it throughout the whole module.
WPropTrigger m_finalizeTrigger
A trigger which can be used to trigger some kind of operation.
osg::ref_ptr< WGEGroupNode > m_moduleNode
Pointer to the modules group node. We need it to be able to update it when callback is invoked.
std::shared_ptr< WValueSet< float > > m_newValueSet
pointer to the created cut valueSet
void createCutDataset()
creates a new dataset
WPosition m_lastMinPos
the last know min position of the ROI if there was any
std::shared_ptr< WTriangleMesh > m_triMesh
This triangle mesh is provided as output through the connector.
std::shared_ptr< std::vector< float > > cutArea(std::shared_ptr< WGrid > inGrid, std::shared_ptr< WValueSet< T > > vals)
copies the data from the input dataset which is marked by the selection box, otherwise data is zero
bool m_showSelector
flag indication if the temporary ROI should be shown;
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...
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
virtual void properties()
Initialize the properties for this module.
Creates a non interpolated triangulation of an isosurface.
Class offering an instantiate-able data connection between modules.
Class representing a single module of OpenWalnut.
Definition: WModule.h:72
virtual void properties()
Initialize properties in this function.
Definition: WModule.cpp:212
void addConnector(std::shared_ptr< WModuleInputConnector > con)
Adds the specified connector to the list of inputs.
Definition: WModule.cpp:108
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
virtual void activate()
Callback for m_active.
Definition: WModule.cpp:220
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 box containing information on an arbitrarily shaped a region of interest.
Definition: WROIArbitrary.h:49
A box representing a region of interest.
Definition: WROIBox.h:49
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.
Base Class for all value set types.
Definition: WValueSet.h:47
@ PV_TRIGGER_TRIGGERED
Trigger property: got triggered.
@ PV_TRIGGER_READY
Trigger property: is ready to be triggered (again)