OpenWalnut  1.5.0dev
WMPaintTexture.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 <sstream>
27 #include <string>
28 #include <vector>
29 
30 #include "WMPaintTexture.h"
31 #include "WMPaintTexture.xpm"
32 #include "core/common/WPropertyHelper.h"
33 #include "core/graphicsEngine/WGEColormapping.h"
34 #include "core/graphicsEngine/WGEUtils.h"
35 #include "core/graphicsEngine/WROIArbitrary.h"
36 #include "core/kernel/WKernel.h"
37 #include "core/kernel/WROIManager.h"
38 #include "core/kernel/WSelectionManager.h"
39 
40 // This line is needed by the module loader to actually find your module. Do not remove. Do NOT add a ";" here.
41 W_LOADABLE_MODULE( WMPaintTexture )
42 
43 WMPaintTexture::WMPaintTexture():
44  WModule()
45 {
46 }
47 
48 WMPaintTexture::~WMPaintTexture()
49 {
50  // Cleanup!
51 }
52 
53 std::shared_ptr< WModule > WMPaintTexture::factory() const
54 {
55  return std::shared_ptr< WModule >( new WMPaintTexture() );
56 }
57 
58 const char** WMPaintTexture::getXPMIcon() const
59 {
60  return paintTexture_xpm; // Please put a real icon here.
61 }
62 const std::string WMPaintTexture::getName() const
63 {
64  return "Paint Texture";
65 }
66 
67 const std::string WMPaintTexture::getDescription() const
68 {
69  return "This module allows painting areas in a 3D texture";
70 }
71 
73 {
74  // the input dataset is just used as source for resolurtion and transformation matrix
75  m_input = std::shared_ptr< WModuleInputData < WDataSetSingle > >(
76  new WModuleInputData< WDataSetSingle >( shared_from_this(), "in", "The input dataset." ) );
78 
79  m_output = std::shared_ptr< WModuleOutputData < WDataSetScalar > >(
80  new WModuleOutputData< WDataSetScalar >( shared_from_this(), "out", "The extracted image." ) );
82 
84 }
85 
87 {
88  m_propCondition = std::shared_ptr< WCondition >( new WCondition() );
89 
90  m_painting = m_properties->addProperty( "Paint", "If active, left click in the scene with pressed ctrl key"
91  " will paint something.", false, m_propCondition );
92 
93  m_pencilSelectionsList = std::shared_ptr< WItemSelection >( new WItemSelection() );
94  m_pencilSelectionsList->addItem( "1x1", "" );
95  m_pencilSelectionsList->addItem( "3x3", "" );
96  m_pencilSelectionsList->addItem( "5x5", "" );
97  m_pencilSelectionsList->addItem( "3x1 (only works on orthogonal slices)", "" );
98  m_pencilSelectionsList->addItem( "5x1 (only works on orthogonal slices)", "" );
99  m_pencilSelection = m_properties->addProperty( "Pencil", "Pencil type.", m_pencilSelectionsList->getSelectorFirst() );
101 
102  m_paintIndex = m_properties->addProperty( "Paint index", "Index we paint into the output texture", 1 );
103  m_paintIndex->setMin( 0 );
104  m_paintIndex->setMax( 255 );
105 
106  m_colorMapSelectionsList = std::shared_ptr< WItemSelection >( new WItemSelection() );
107  m_colorMapSelectionsList->addItem( "Grayscale", "" );
108  m_colorMapSelectionsList->addItem( "Rainbow", "" );
109  m_colorMapSelectionsList->addItem( "Hot iron", "" );
110  m_colorMapSelectionsList->addItem( "Red-Yellow", "" );
111  m_colorMapSelectionsList->addItem( "Atlas", "" );
112  m_colorMapSelectionsList->addItem( "Blue-Green-Purple", "" );
113 
114  m_colorMapSelection = m_properties->addProperty( "Colormap", "Colormap type.", m_colorMapSelectionsList->getSelector( 4 ), m_propCondition );
116 
117  m_queueAdded = m_properties->addProperty( "Something paint", "", false, m_propCondition );
118  m_queueAdded->setHidden();
119 
120  m_buttonCopyFromInput = m_properties->addProperty( "Copy from input", "Copies data from the input dataset into the paint texture",
122 
123  m_buttonUpdateOutput = m_properties->addProperty( "Update output", "Updates the output connector",
125  m_buttonCreateRoi = m_properties->addProperty( "Create ROI", "Create a ROI from the currently selected paint value",
127 
129 }
130 
132 {
133  boost::signals2::connection con = WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getPickHandler()->getPickSignal()->
134  connect( boost::bind( &WMPaintTexture::queuePaint, this, boost::placeholders::_1 ) );
135 
136  m_moduleState.setResetable( true, true );
137  m_moduleState.add( m_input->getDataChangedCondition() );
139  m_moduleState.add( m_active->getUpdateCondition() );
140 
141  ready();
142 
143  while( !m_shutdownFlag() )
144  {
146 
147  if( m_shutdownFlag() )
148  {
149  break;
150  }
151 
152  std::shared_ptr< WDataSetSingle > newDataSet = m_input->getData();
153  bool dataChanged = ( m_dataSet != newDataSet );
154  bool dataValid = ( newDataSet != NULL );
155 
156  if( dataValid )
157  {
158  if( dataChanged )
159  {
160  m_dataSet = newDataSet;
161  WAssert( m_dataSet, "" );
162  WAssert( m_dataSet->getValueSet(), "" );
163 
164  createTexture();
165 
167  }
168 
169  if( m_painting->changed() )
170  {
171  if( m_painting->get( true ) )
172  {
173  WKernel::getRunningKernel()->getSelectionManager()->setPaintMode( PAINTMODE_PAINT );
174  }
175  else
176  {
177  WKernel::getRunningKernel()->getSelectionManager()->setPaintMode( PAINTMODE_NONE );
178  }
179  }
180 
181  if( m_active->changed() )
182  {
183  if( m_active->get( true ) )
184  {
185  if( m_painting->get( true ) )
186  {
187  WKernel::getRunningKernel()->getSelectionManager()->setPaintMode( PAINTMODE_PAINT );
188  }
189  if( m_texture )
190  {
191  m_texture->active()->set( true );
192  }
193  }
194  else
195  {
196  m_texture->active()->set( false );
197  WKernel::getRunningKernel()->getSelectionManager()->setPaintMode( PAINTMODE_NONE );
198  }
199  }
200 
202  {
203  copyFromInput();
205  }
206 
208  {
209  m_painting->set( false );
210  createROI();
212  }
213  }
214  else // case !dataValid
215  {
216  if( m_outData )
217  m_outData = std::shared_ptr< WDataSetScalar >();
218  m_output->updateData( m_outData );
219  }
220  if( m_queueAdded->changed() && m_queueAdded->get( true ) )
221  {
222  doPaint();
223  }
224 
226  {
229  }
230  }
231 
232  debugLog() << "Shutting down...";
233 
235  WKernel::getRunningKernel()->getSelectionManager()->setPaintMode( PAINTMODE_NONE );
236 
237  con.disconnect();
238 
239  debugLog() << "Finished! Good Bye!";
240 }
241 
243 {
245 }
246 
248 {
249  unsigned char* data = m_texture->getImage()->data();
250 
251  while( !m_paintQueue.empty() )
252  {
253  WPickInfo pickInfo = m_paintQueue.front();
254  WPosition paintPosition = pickInfo.getPickPosition();
255  m_paintQueue.pop();
256 
257  int voxelNum = m_grid->getVoxelNum( paintPosition );
258  if( voxelNum != -1 )
259  {
260  switch( m_pencilSelection->get( true ).getItemIndexOfSelected( 0 ) )
261  {
262  case 0:
263  data[ voxelNum ] = m_paintIndex->get();
264  break;
265  case 1:
266  {
267  data[ voxelNum ] = m_paintIndex->get();
268  std::vector< size_t > ids = m_grid->getNeighbours27( voxelNum );
269  for( size_t i = 0; i < ids.size(); ++i )
270  {
271  data[ ids[i] ] = m_paintIndex->get();
272  }
273  break;
274  }
275  case 2:
276  {
277  data[ voxelNum ] = m_paintIndex->get();
278  std::vector< size_t > ids = m_grid->getNeighbours27( voxelNum );
279  for( size_t i = 0; i < ids.size(); ++i )
280  {
281  std::vector< size_t > allIds = m_grid->getNeighbours27( ids[i] );
282  for( size_t k = 0; k < allIds.size(); ++k )
283  {
284  data[ allIds[k] ] = m_paintIndex->get();
285  }
286  }
287  break;
288  }
289  case 3:
290  {
291  if( pickInfo.getName() == "Axial Slice" )
292  {
293  data[ voxelNum ] = m_paintIndex->get();
294  std::vector< size_t > ids = m_grid->getNeighbours9XY( voxelNum );
295  for( size_t i = 0; i < ids.size(); ++i )
296  {
297  data[ ids[i] ] = m_paintIndex->get();
298  }
299  }
300  if( pickInfo.getName() == "Coronal Slice" )
301  {
302  data[ voxelNum ] = m_paintIndex->get();
303  std::vector< size_t > ids = m_grid->getNeighbours9XZ( voxelNum );
304  for( size_t i = 0; i < ids.size(); ++i )
305  {
306  data[ ids[i] ] = m_paintIndex->get();
307  }
308  }
309  if( pickInfo.getName() == "Sagittal Slice" )
310  {
311  data[ voxelNum ] = m_paintIndex->get();
312  std::vector< size_t > ids = m_grid->getNeighbours9YZ( voxelNum );
313  for( size_t i = 0; i < ids.size(); ++i )
314  {
315  data[ ids[i] ] = m_paintIndex->get();
316  }
317  }
318  break;
319  }
320  case 4:
321  {
322  if( pickInfo.getName() == "Axial Slice" )
323  {
324  data[ voxelNum ] = m_paintIndex->get();
325  std::vector< size_t > ids = m_grid->getNeighbours9XY( voxelNum );
326  for( size_t i = 0; i < ids.size(); ++i )
327  {
328  std::vector< size_t > allIds = m_grid->getNeighbours9XY( ids[i] );
329  for( size_t k = 0; k < allIds.size(); ++k )
330  {
331  data[ allIds[k] ] = m_paintIndex->get();
332  }
333  }
334  }
335  if( pickInfo.getName() == "Coronal Slice" )
336  {
337  data[ voxelNum ] = m_paintIndex->get();
338  std::vector< size_t > ids = m_grid->getNeighbours9XZ( voxelNum );
339  for( size_t i = 0; i < ids.size(); ++i )
340  {
341  std::vector< size_t > allIds = m_grid->getNeighbours9XZ( ids[i] );
342  for( size_t k = 0; k < allIds.size(); ++k )
343  {
344  data[ allIds[k] ] = m_paintIndex->get();
345  }
346  }
347  }
348  if( pickInfo.getName() == "Sagittal Slice" )
349  {
350  data[ voxelNum ] = m_paintIndex->get();
351  std::vector< size_t > ids = m_grid->getNeighbours9YZ( voxelNum );
352  for( size_t i = 0; i < ids.size(); ++i )
353  {
354  std::vector< size_t > allIds = m_grid->getNeighbours9YZ( ids[i] );
355  for( size_t k = 0; k < allIds.size(); ++k )
356  {
357  data[ allIds[k] ] = m_paintIndex->get();
358  }
359  }
360  }
361  break;
362  }
363 
364  default:
365  break;
366  }
367  }
368  }
369  m_queueAdded->set( false );
370 
371  m_texture->dirtyTextureObject();
372 
374 }
375 
377 {
378  if( pickInfo.getModifierKey() == WPickInfo::SHIFT )
379  {
380  setColorFromPick( pickInfo );
381  return;
382  }
383 
384  if( !m_painting->get() || ( pickInfo.getMouseButton() != WPickInfo::MOUSE_LEFT ) || ( pickInfo.getName() == WPickHandler::unpickString ) )
385  {
386  return;
387  }
388 
389  m_paintQueue.push( pickInfo );
390  m_queueAdded->set( true );
391 }
392 
394 {
395  WPosition paintPosition = pickInfo.getPickPosition();
396  int voxelNum = m_grid->getVoxelNum( paintPosition );
397 
398  if( voxelNum != -1 )
399  {
400  unsigned char* data = m_texture->getImage()->data();
401  m_paintIndex->set( data[ voxelNum ] );
402  }
403 }
404 
406 {
407  m_grid = std::dynamic_pointer_cast< WGridRegular3D >( m_dataSet->getGrid() );
408 
409  osg::ref_ptr< osg::Image > ima = new osg::Image;
410  ima->allocateImage( m_grid->getNbCoordsX(), m_grid->getNbCoordsY(), m_grid->getNbCoordsZ(), GL_LUMINANCE, GL_UNSIGNED_BYTE );
411 
412  unsigned char* data = ima->data();
413 
414  for( unsigned int i = 0; i < m_grid->size(); ++i )
415  {
416  data[i] = 0.0;
417  }
418 
419  m_texture = osg::ref_ptr< WGETexture3D >( new WGETexture3D( ima ) );
420  m_texture->setFilterMinMag( osg::Texture3D::LINEAR );
421  m_texture->setWrapSTR( osg::Texture::CLAMP_TO_BORDER );
422  m_texture->colormap()->set( m_texture->colormap()->get().newSelector( WItemSelector::IndexList( 1, 4 ) ) );
423  m_properties->addProperty( m_texture->alpha() );
424 
425  WGEColormapping::registerTexture( m_texture, "Painted Texture" );
426 }
427 
429 {
430  WAssert( m_dataSet, "" );
431  WAssert( m_dataSet->getValueSet(), "" );
432  WAssert( m_dataSet->getGrid(), "" );
433 
434  unsigned char* data = m_texture->getImage()->data();
435  std::shared_ptr< std::vector< unsigned char > > values =
436  std::shared_ptr< std::vector< unsigned char > >( new std::vector< unsigned char >( m_grid->size(), 0.0 ) );
437 
438  for( unsigned int i = 0; i < m_grid->size(); ++i )
439  {
440  ( *values )[i] = data[i];
441  }
442 
443  std::shared_ptr< WValueSet< unsigned char > > vs =
444  std::shared_ptr< WValueSet< unsigned char > >( new WValueSet< unsigned char >( 0, 1, values, W_DT_UINT8 ) );
445 
446  m_outData = std::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, m_grid ) );
447  m_outData->getTexture()->interpolation()->set( false );
448  m_output->updateData( m_outData );
449 }
450 
452 {
453  m_grid = std::dynamic_pointer_cast< WGridRegular3D >( m_dataSet->getGrid() );
454 
455  unsigned char* data = m_texture->getImage()->data();
456 
457  std::shared_ptr< WValueSet< unsigned char > > vals;
458  vals = std::dynamic_pointer_cast< WValueSet< unsigned char > >( m_dataSet->getValueSet() );
459 
460  for( unsigned int i = 0; i < m_grid->size(); ++i )
461  {
462  data[i] = vals->getScalar( i );
463  }
464  m_texture->dirtyTextureObject();
465 }
466 
468 {
469  bool valid = false;
470  std::vector<float>roiVals( m_grid->size(), 0 );
471  unsigned char index = m_paintIndex->get();
472 
473  unsigned char* data = m_texture->getImage()->data();
474 
475  for( size_t i = 0; i < m_grid->size(); ++i )
476  {
477  if( data[i] == index )
478  {
479  roiVals[i] = 1.0;
480  valid = true;
481  }
482  }
483 
484  if( valid )
485  {
486  osg::ref_ptr< WROI > newRoi = osg::ref_ptr< WROI >(
487  new WROIArbitrary( m_grid->getNbCoordsX(), m_grid->getNbCoordsY(), m_grid->getNbCoordsZ(),
488  m_grid->getTransformationMatrix(), roiVals, 1.0, wge::createColorFromIndex( index ) ) );
489 
490  if( WKernel::getRunningKernel()->getRoiManager()->getSelectedRoi() == NULL )
491  {
492  WLogger::getLogger()->addLogMessage( " new roi without parent ", "WMPaintTexture", LL_DEBUG );
493  WKernel::getRunningKernel()->getRoiManager()->addRoi( newRoi );
494  }
495  else
496  {
497  WLogger::getLogger()->addLogMessage( " new roi with parent ", "WMPaintTexture", LL_DEBUG );
498  WKernel::getRunningKernel()->getRoiManager()->addRoi( newRoi, WKernel::getRunningKernel()->getRoiManager()->getSelectedRoi() );
499  }
500  }
501 }
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
This data set type contains scalars as values.
static void registerTexture(osg::ref_ptr< WGETexture3D > texture, std::string name="")
Register the specified texture to the colormapper.
static void deregisterTexture(osg::ref_ptr< WGETexture3D > texture)
De-register the specified texture to the colormapper.
This calls serves a simple purpose: have a texture and its scaling information together which allows ...
Definition: WGETexture.h:53
A class containing a list of named items.
std::vector< size_t > IndexList
The type used for storing index lists.
Definition: WItemSelector.h:59
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
void addLogMessage(std::string message, std::string source="", LogLevel level=LL_DEBUG)
Appends a log message to the logging queue.
Definition: WLogger.cpp:84
static WLogger * getLogger()
Returns pointer to the currently running logger instance.
Definition: WLogger.cpp:64
Forward declaration of WPickInfo.
virtual void moduleMain()
Entry point after loading the module.
WPropSelection m_colorMapSelection
Selection property for color map.
WPropTrigger m_buttonCreateRoi
updates the output connector on demand, as we don't want to do this every paint command
void copyFromInput()
copies data from the input dataset into the paint texture
void doPaint()
this function listens to the pick handler, if the paint flag is true it will write into the out textu...
WPropBool m_painting
Interpolation?
std::shared_ptr< WDataSetSingle > m_dataSet
This is a pointer to the dataset the module is currently working on.
void setColorFromPick(WPickInfo pickInfo)
get the paint index at the picked voexel fromt he out texture and sets m_paintIndex accordingly
WPropSelection m_pencilSelection
Selection property for pencil size and shape.
WPropTrigger m_buttonCopyFromInput
copies the input dataset into the paint texture, this allows one to continue work
std::shared_ptr< WDataSetScalar > m_outData
This is a pointer to the current output.
std::shared_ptr< WGridRegular3D > m_grid
stores a pointer to the grid we use;
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
virtual void connectors()
Initialize the connectors this module is using.
WPropTrigger m_buttonUpdateOutput
updates the output connector on demand, as we don't want to do this every paint command
WPropInt m_paintIndex
specifies the value we paint into the output texture
void createROI()
creates a ROI from the currently selected paint value
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
void updateOutDataset()
updates the output connector
virtual const std::string getDescription() const
Gives back a description of this module.
std::shared_ptr< WModuleOutputData< WDataSetScalar > > m_output
An output connector for the output scalar dsataset.
osg::ref_ptr< WGETexture3D > m_texture
stores a pointer to the texture we paint in
std::shared_ptr< WItemSelection > m_pencilSelectionsList
A list of pencil sizes and shapes.
std::queue< WPickInfo > m_paintQueue
new paint coordinates get added here
virtual void properties()
Initialize the properties for this module.
std::shared_ptr< WItemSelection > m_colorMapSelectionsList
A list of color map selection types.
virtual void activate()
Callback for m_active.
std::shared_ptr< WModuleInputData< WDataSetSingle > > m_input
An input connector that accepts order 1 datasets.
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 createTexture()
creates a new texture
WPropBool m_queueAdded
true when a new paint coordinate is added to the queue
void queuePaint(WPickInfo pickInfo)
this function listens to the pick handler, if the paint flag is true it will add the paint position t...
virtual const std::string getName() const
Gives back the name of this module.
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
wlog::WStreamedLogger debugLog() const
Logger instance for comfortable debug logging.
Definition: WModule.cpp:575
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
static const std::string unpickString
The string indicating picking has stopped.
Definition: WPickHandler.h:104
Encapsulates info for pick action.
Definition: WPickInfo.h:42
WPosition getPickPosition() const
Get position where object was hit.
Definition: WPickInfo.h:253
WMouseButton getMouseButton() const
Get the mouse button associated with the pick.
Definition: WPickInfo.h:233
std::string getName() const
Get name of picked object.
Definition: WPickInfo.h:243
modifierKey getModifierKey() const
Get the modifier key associated with the pick.
Definition: WPickInfo.h:223
This only is a 3d double vector.
A box containing information on an arbitrarily shaped a region of interest.
Definition: WROIArbitrary.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)
void addTo(WPropSelection prop)
Add the PC_SELECTONLYONE constraint to the property.
WColor createColorFromIndex(int index)
creates the same color as the atlas colormap shader from the index
Definition: WGEUtils.cpp:62