OpenWalnut  1.5.0dev
WMPointConnector.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 #define _USE_MATH_DEFINES
26 
27 #include <chrono>
28 #include <cmath>
29 #include <memory>
30 #include <string>
31 #include <vector>
32 
33 #include "WAngleHelper.h"
34 #include "WConnectorData.h"
35 #include "WFiberHandler.h"
36 #include "WKeyboardHandler.h"
37 #include "WMPointConnector.h"
38 
39 static const osg::Vec4 COLOR_SEL_POINT( 255.0 / 255.0, 190.0 / 255.0, 7.0 / 255.0, 1.0 );
40 static const osg::Vec4 COLOR_SEL_FIBER( 30.0 / 255.0, 136.0 / 255.0, 229.0 / 255.0, 1.0 );
41 static const osg::Vec4 COLOR_PRE_POINT( 255.0 / 255.0, 0.0 / 255.0, 0.0 / 255.0, 1.0 );
42 
43 
44 W_LOADABLE_MODULE( WMPointConnector )
45 
48 {
49  m_connectorData = WConnectorData::SPtr( new WConnectorData() );
50  m_fiberHandler = WFiberHandler::SPtr( new WFiberHandler( this ) );
51  m_eventCondition = WCondition::SPtr( new WCondition() );
52 }
53 
55 {
57 }
58 
59 std::shared_ptr< WModule > WMPointConnector::factory() const
60 {
61  return std::shared_ptr< WModule >( new WMPointConnector() );
62 }
63 
64 const char** WMPointConnector::getXPMIcon() const
65 {
66  return NULL;
67 }
68 
69 const std::string WMPointConnector::getName() const
70 {
71  return "Point Connector";
72 }
73 
74 const std::string WMPointConnector::getDescription() const
75 {
76  return "Allows user to manually connect points to fibers.";
77 }
78 
80 {
81  m_pointInput = WModuleInputData< WDataSetPoints >::createAndAdd( shared_from_this(), "points in", "The data to display" );
82 
83  m_pointOutput = WModuleOutputData< WDataSetPoints >::create( shared_from_this(), "points out", "The data that is passed internally" );
84  m_fiberOutput = WModuleOutputData< WDataSetFibers >::createAndAdd( shared_from_this(), "fibers out", "The created fibers" );
85 
87 }
88 
90 {
91  m_fiberHandler->createProperties( m_properties );
92 
93  auto updateFunction = [this]( auto )
94  {
95  pushEventQueue( std::bind( &WMPointConnector::updateAll, this ) );
96  };
97 
98  WPropertyGroup::SPtr assistanceGroup = m_properties->addPropertyGroup( "Assistance", "Property group assistance features." );
99 
100  m_enableSAPT = assistanceGroup->addProperty( "Enable SAPT ", "Enable Semi-Automatic-Particle-Tracking", true );
101  m_enablePrediction = assistanceGroup->addProperty( "Enable prediction", "Enables the prediction of tracks", true, updateFunction );
102  m_enableSizes = assistanceGroup->addProperty( "Enable sizes", "Enables the point size based on the cluster size", false,
103  updateFunction );
104  m_enableAdaptiveVisibility = assistanceGroup->addProperty( "Enable adaptive visibility", "Enable adaptive visibility using a cone", true,
105  updateFunction );
106  m_adaptiveVisibilityAngle = assistanceGroup->addProperty( "Adaptive visibility angle", "Adaptive visibility angle", 10.0, updateFunction );
107  m_adaptiveVisibilityAngle->setMin( 0.0 );
108  m_adaptiveVisibilityAngle->setMax( 90.0 );
109 
110  m_hiddenOpacity = assistanceGroup->addProperty( "Hidden point opacity", "Changes the opacity of the hidden points", 0.1, updateFunction );
111  m_hiddenOpacity->setMin( 0.0 );
112  m_hiddenOpacity->setMax( 1.0 );
113 
114  m_scaling = assistanceGroup->addProperty( "Scaling", "Changes the scaling", WPosition( 1.0, 1.0, 1.0 ), updateFunction );
115 
117 }
118 
120 {
121  createHandler();
122 
123  m_onscreenSelection = std::shared_ptr< WOnscreenSelection >( new WOnscreenSelection() );
124  m_onscreenSelection->setOnend( boost::bind( &WMPointConnector::selectionEnd, this,
125  boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3 ) );
126 
127  m_moduleState.setResetable( true, true );
128  m_moduleState.add( m_pointInput->getDataChangedCondition() );
130 
133 
134  ready();
135 
136  while( !m_shutdownFlag() )
137  {
138  debugLog() << "Waiting ...";
140 
141  if( m_shutdownFlag() )
142  {
143  break;
144  }
145 
146  std::shared_ptr< WProgress > progressBar( new WProgress( "Work event queue..." ) );
147  m_progress->addSubProgress( progressBar );
148  // Handle queue
149  {
150  std::unique_lock< std::mutex > lock( m_eventMutex );
151 
152  // copy and handle later so concurrent lock calls don't hang the gui thread
153  std::vector< std::function< void() > > qu( m_eventQueue );
154  m_eventQueue.clear();
155 
156  lock.unlock();
157 
158  // Handle every function in the current queue
159  while( !qu.empty() )
160  {
161  qu.back()();
162  qu.pop_back();
163  }
164  }
165  progressBar->finish();
166 
167  if( m_pointInput->updated() )
168  {
169  handleInput();
170  }
171  }
172 
173  WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getView()->removeEventHandler( m_keyboardHandler.get() );
174 
175  stop();
176 }
177 
179 {
180  m_pointRenderer->getProperties()->getProperty( "active" )->toPropBool()->set( m_active->get() );
181  m_fiberDisplay->getProperties()->getProperty( "active" )->toPropBool()->set( m_active->get() );
182 }
183 
185 {
186  WPropertyGroup::SPtr pointGroup = m_properties->addPropertyGroup( "Point Renderer", "Properties passed through from the point renderer" );
187 
188  m_pointRenderer = createAndAdd( "Point Renderer" );
189  m_pointRenderer->isReady().wait();
190  m_pointOutput->connect( m_pointRenderer->getInputConnector( "points" ) );
191 
192  pointGroup->addProperty( "Activate", "Activates the point renderer", true,
194 
195  pointGroup->addProperty( m_pointRenderer->getProperties()->getProperty( "Point size" ) );
196 }
197 
199 {
200  WPropertyGroup::SPtr fiberGroup = m_properties->addPropertyGroup( "Fiber Display", "Properties passed through from the fiber display" );
201 
202  m_fiberDisplay = createAndAdd( "Fiber Display" );
203  m_fiberDisplay->isReady().wait();
204  m_fiberOutput->connect( m_fiberDisplay->getInputConnector( "fibers" ) );
205 
206  fiberGroup->addProperty( "Activate", "Activates the fiber display", true,
208 
209  fiberGroup->addProperty( m_fiberDisplay->getProperties()->getProperty( "Line Rendering" )->toPropGroup()->getProperty( "Line width" ) );
210 }
211 
213 {
214  WPropBool active = mod->getProperties()->getProperty( "active" )->toPropBool();
215  active->set( !active->get() );
216 }
217 
219 {
220  osg::ref_ptr< osgViewer::View > viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getView();
221 
222  m_keyboardHandler = new WKeyboardHandler( this );
223  viewer->addEventHandler( m_keyboardHandler.get() );
224 }
225 
227 {
228  WDataSetPoints::SPtr points = m_pointInput->getData();
229  if( !points )
230  {
231  debugLog() << "Invalid Data. Break.";
232  return;
233  }
234 
235  SPFloatVector edeps;
236  SPSizeVector eventIDs;
237  std::shared_ptr< WValueSet< float > > clusterSizes;
238 
239  if( points->getData().type() == typeid( std::tuple< SPFloatVector > ) )
240  {
241  edeps = std::get< 0 >( std::any_cast< std::tuple< SPFloatVector > >( points->getData() ) );
242  }
243  else if( points->getData().type() == typeid( std::tuple< SPSizeVector > ) )
244  {
245  eventIDs = std::get< 0 >( std::any_cast< std::tuple< SPSizeVector > >( points->getData() ) );
246  }
247  else if( points->getData().type() == typeid( std::tuple< SPFloatVector, SPSizeVector > ) )
248  {
249  edeps = std::get< 0 >( std::any_cast< std::tuple< SPFloatVector, SPSizeVector > >( points->getData() ) );
250  eventIDs = std::get< 1 >( std::any_cast< std::tuple< SPFloatVector, SPSizeVector > >( points->getData() ) );
251  }
252  else if( points->getData().type() == typeid( std::shared_ptr< WValueSet< float > > ) )
253  {
254  clusterSizes = std::any_cast< std::shared_ptr< WValueSet< float > > >( points->getData() );
255  }
256 
257  m_connectorData->clear();
258 
259  m_fiberHandler->clear();
260 
261  WFiberHandler::PCFiberListSPtr fibers = m_fiberHandler->getFibers();
262 
263  for( size_t pointIdx = 0; pointIdx < points->size(); ++pointIdx )
264  {
265  osg::Vec3 vertex = points->operator[]( pointIdx );
266  m_connectorData->addVertex( vertex,
267  points->getColor( pointIdx ),
268  edeps ? edeps->at( pointIdx ) : 0.0,
269  clusterSizes ? clusterSizes->getScalar( pointIdx ) : 0.0 );
270 
271  if( eventIDs )
272  {
273  size_t eventID = eventIDs->at( pointIdx );
274 
275  while( fibers->size() <= eventID )
276  {
277  m_fiberHandler->addFiber( "Track " + boost::lexical_cast< std::string >( fibers->size() ), true, false );
278  }
279 
280  ( fibers->begin() + eventID )->push_back( vertex );
281  }
282  }
283 
284  for( size_t idx = fibers->size() - 1; idx > 0; idx-- )
285  {
286  if( fibers->at( idx ).size() <= 1 )
287  {
288  m_fiberHandler->removeFiber( idx, true, false );
289  }
290  }
291 
292  m_fiberHandler->setFiberCount( fibers->size() );
293  m_fiberHandler->selectorUpdate( fibers->size() - 1 );
294 
295  m_fiberHandler->sortVertices();
296 
297  if( clusterSizes )
298  {
299  m_connectorData->setHasClusterSize();
300  }
301 
302  updateAll();
303 }
304 
306 {
307  m_prediction.clear();
308 
309  if( m_enableAdaptiveVisibility == NULL || m_enablePrediction == NULL )
310  {
311  return;
312  }
313 
314  if( !m_enableAdaptiveVisibility->get() || !m_enablePrediction->get() )
315  {
316  return;
317  }
318 
319  WFiberHandler::PCFiber fiber = m_fiberHandler->getFibers()->at( m_fiberHandler->getSelectedFiber() );
320 
321  if( fiber.size() < 2 )
322  {
323  return;
324  }
325 
326  for( size_t idx = 0; idx < m_connectorData->getVertices()->size(); idx++ )
327  {
328  osg::Vec3 vertex = m_connectorData->getVertices()->at( idx );
329  double layerDiffFront = ( fiber.front().z() - vertex.z() ) / 5.5;
330  double layerDiffBack = ( vertex.z() - fiber.back().z() ) / 5.5;
331 
332  if( ( ( layerDiffFront <= 3 && layerDiffFront > 0 && !isAdaptivelyHidden( vertex, &fiber.front() ) )
333  || ( layerDiffBack <= 3 && layerDiffBack > 0 && !isAdaptivelyHidden( vertex, &fiber.back() ) ) )
334  && !m_fiberHandler->isPointHidden( vertex ) )
335  {
336  m_prediction.push_back( vertex );
337  }
338  }
339 
341 }
342 
344 {
346  updatePoints();
347  updateOutput();
348 }
349 
351 {
352  if( m_pointRenderer == NULL )
353  {
354  return;
355  }
356 
357  if( m_connectorData->getVertices()->size() == 0 )
358  {
359  m_pointOutput->updateData( NULL );
360  return;
361  }
362 
363  WDataSetPoints::VertexArray vertices( new std::vector< float > );
364  WDataSetPoints::VertexArray colors( new std::vector< float > );
365 
366  for( size_t idx = 0; idx < m_connectorData->getVertices()->size(); idx++ )
367  {
368  osg::Vec3 vertex = m_connectorData->getVertices()->at( idx );
369  osg::Vec4 color( 1.0, 1.0, 1.0, 1.0 );
370 
371  vertices->push_back( vertex.x() * m_scaling->get().x() );
372  vertices->push_back( vertex.y() * m_scaling->get().y() );
373  vertices->push_back( vertex.z() * m_scaling->get().z() );
374 
375  size_t tmpIdx;
376  if( m_connectorData->getSelectedPoint( &tmpIdx ) && tmpIdx == idx )
377  {
378  color = COLOR_SEL_POINT;
379  }
380  else if( m_fiberHandler->getFiberOfPoint( vertex, &tmpIdx ) && m_fiberHandler->getSelectedFiber() == tmpIdx )
381  {
382  color = COLOR_SEL_FIBER;
383  }
384  else if( std::find( m_prediction.begin(), m_prediction.end(), WPosition( vertex ) ) != m_prediction.end() )
385  {
386  color = COLOR_PRE_POINT;
387  }
388  else if( m_fiberHandler->isPointHidden( vertex ) || isAdaptivelyHidden( vertex ) )
389  {
390  color[3] = m_hiddenOpacity->get();
391  }
392 
393  colors->push_back( color.x() );
394  colors->push_back( color.y() );
395  colors->push_back( color.z() );
396  colors->push_back( color.w() );
397  }
398 
399  std::any data = NULL;
400  if( m_connectorData->hasClusterSize() && m_enableSizes->get() )
401  {
402  data = std::shared_ptr< WValueSet< float > >( new WValueSet< float >( 0, 1, m_connectorData->getClusterSizes() ) );
403  }
404 
405  m_pointOutput->updateData( WDataSetPoints::SPtr( new WDataSetPoints( vertices, colors, data ) ) );
406 }
407 
408 bool WMPointConnector::isAdaptivelyHidden( osg::Vec3 vertex, osg::Vec3* from )
409 {
410  if( !m_enableAdaptiveVisibility->get() )
411  {
412  return false;
413  }
414 
415  osg::Vec3 selected;
416 
417  if( from != NULL )
418  {
419  selected = *from;
420  }
421  else
422  {
423  size_t verIdx = 0;
424  if( !m_connectorData->getSelectedPoint( &verIdx ) )
425  {
426  return false;
427  }
428 
429  selected = m_connectorData->getVertices()->at( verIdx );
430  }
431 
432  WFiberHandler::PCFiber fiber = m_fiberHandler->getFibers()->at( m_fiberHandler->getSelectedFiber() );
433  if( fiber.size() < 2 )
434  {
435  return false;
436  }
437 
438  auto it = std::find( fiber.begin(), fiber.end(), selected );
439  osg::Vec3 before = osg::Vec3( 0.0, 0.0, 1.0 );
440  if( it != fiber.end() && it != fiber.begin() )
441  {
442  before = *( --it );
443  }
444 
445  double angle = WAngleHelper::calculateAngle( selected - before, vertex - selected );
446 
447  double layerDiff = abs( selected.z() - vertex.z() ) / 5.5; // 5.5 is the general layer thickness
448 
449  double checkAngle = m_adaptiveVisibilityAngle->get() * layerDiff;
450 
451  return angle > checkAngle && angle < ( 180.0 - checkAngle );
452 }
453 
454 void WMPointConnector::handleClick( osg::Vec3 cameraPosition, osg::Vec3 direction, bool isLeftClick )
455 {
456  size_t hitIdx = 0;
457 
458  if( findClickedPoint( cameraPosition, direction, &hitIdx ) )
459  {
460  if( isLeftClick )
461  {
462  size_t fiberIdx = 0;
463  if( m_fiberHandler->getFiberOfPoint( m_connectorData->getVertices()->at( hitIdx ), &fiberIdx ) )
464  {
465  if( m_fiberHandler->getSelectedFiber() == fiberIdx )
466  {
467  m_connectorData->selectPoint( hitIdx );
468  }
469  else
470  {
471  m_fiberHandler->selectFiber( fiberIdx );
472  m_fiberHandler->selectorUpdate( fiberIdx );
473  }
474  }
475  else
476  {
477  m_connectorData->deselectPoint();
478  m_connectorData->selectPoint( hitIdx );
479  m_fiberHandler->addVertexToFiber( m_connectorData->getVertices()->at( hitIdx ), m_fiberHandler->getSelectedFiber() );
480  }
481  }
482  else
483  {
484  m_connectorData->deselectPoint();
485  m_fiberHandler->removeVertexFromFiber( m_connectorData->getVertices()->at( hitIdx ), m_fiberHandler->getSelectedFiber() );
486  m_fiberHandler->selectLastPoint();
487  }
488 
489  updateAll();
490  }
491 }
492 
493 
494 bool WMPointConnector::findClickedPoint( osg::Vec3 cameraPosition, osg::Vec3 direction, size_t* hitIdx )
495 {
496  bool hasHit = false;
497  float distance = 0;
498  float size = m_pointRenderer->getProperties()->getProperty( "Point size" )->toPropDouble()->get();
499  for( size_t idx = 0; idx < m_connectorData->getVertices()->size(); idx++ )
500  {
501  osg::Vec3 vertex = m_connectorData->getVertices()->at( idx );
502  vertex = osg::Vec3( vertex.x() * m_scaling->get().x(), vertex.y() * m_scaling->get().y(), vertex.z() * m_scaling->get().z() );
503  float localSize = size;
504  if( m_connectorData->hasClusterSize() && m_enableSizes->get() )
505  {
506  localSize *= m_connectorData->getClusterSizes()->at( idx );
507  }
508 
509  float hit = hitVertex( cameraPosition, direction, vertex, localSize );
510  if( hit > 0.0 )
511  {
512  float dis = ( vertex - cameraPosition ).length2();
513  if( !hasHit )
514  {
515  hasHit = true;
516  distance = dis;
517  *hitIdx = idx;
518  }
519  else if( dis < distance )
520  {
521  distance = dis;
522  *hitIdx = idx;
523  }
524  }
525  }
526 
527  return hasHit;
528 }
529 
530 float WMPointConnector::hitVertex( osg::Vec3 rayStart, osg::Vec3 rayDir, osg::Vec3 vertex, float radius )
531 {
532  osg::Vec3 oc = rayStart - vertex;
533  float a = rayDir * rayDir;
534  float b = 2.0 * ( oc * rayDir );
535  float c = ( oc * oc ) - radius * radius;
536  float discriminant = b * b - 4 * a * c;
537 
538  if( discriminant < 0.0 )
539  {
540  return -1.0;
541  }
542  else if( discriminant == 0.0 )
543  {
544  return 0.0;
545  }
546  else
547  {
548  float sqrtDis = sqrt( discriminant );
549  float numerator = -b - sqrtDis;
550  if( numerator > 0.0 )
551  {
552  return numerator / ( 2.0 * a );
553  }
554 
555  numerator = -b + sqrtDis;
556  if( numerator > 0.0 )
557  {
558  return numerator / ( 2.0 * a );
559  }
560  else
561  {
562  return -1.0;
563  }
564  }
565 }
566 
568 {
569  if( m_fiberDisplay == NULL )
570  {
571  return;
572  }
573 
574  std::shared_ptr< std::vector< float > > vertices = std::shared_ptr< std::vector< float > >( new std::vector< float >() );
575  std::shared_ptr< std::vector< float > > colors = std::shared_ptr< std::vector< float > >( new std::vector< float >() );
576  std::shared_ptr< std::vector< size_t > > lineStartIndexes = std::shared_ptr< std::vector< size_t > >( new std::vector< size_t >() );
577  std::shared_ptr< std::vector< size_t > > lineLength = std::shared_ptr< std::vector< size_t > >( new std::vector< size_t >() );
578  std::shared_ptr< std::vector< size_t > > verticesReverse = std::shared_ptr< std::vector< size_t > >( new std::vector< size_t >() );
579 
580  for( size_t idx = 0; idx < m_fiberHandler->getFibers()->size(); idx++ )
581  {
582  WFiberHandler::PCFiber fiber = m_fiberHandler->getFibers()->at( idx );
583  if( fiber.size() < 2 )
584  {
585  continue;
586  }
587 
588  lineStartIndexes->push_back( vertices->size() / 3 );
589  lineLength->push_back( fiber.size() );
590 
591  osg::Vec4 color( 0.0, 0.0, 0.0, 1.0 );
592  if( m_fiberHandler->getSelectedFiber() == idx )
593  {
594  color = COLOR_SEL_FIBER;
595  }
596 
597  if( m_fiberHandler->isHidden( idx ) )
598  {
599  color[3] = m_hiddenOpacity->get();
600  }
601 
602  for( size_t vIdx = 0; vIdx < fiber.size(); vIdx++ )
603  {
604  osg::Vec3 vertex = fiber[vIdx];
605  vertices->push_back( vertex.x() * m_scaling->get().x() );
606  vertices->push_back( vertex.y() * m_scaling->get().y() );
607  vertices->push_back( vertex.z() * m_scaling->get().z() );
608 
609  colors->push_back( color.x() );
610  colors->push_back( color.y() );
611  colors->push_back( color.z() );
612  colors->push_back( color.w() );
613 
614  verticesReverse->push_back( idx );
615  }
616  }
617 
618  WDataSetFibers::SPtr fibers(
619  new WDataSetFibers(
620  vertices,
621  lineStartIndexes,
622  lineLength,
623  verticesReverse
624  )
625  );
626 
627  if( vertices->size() == 0 )
628  {
629  m_fiberOutput->updateData( NULL );
630  return;
631  }
632 
633  fibers->addColorScheme( colors, "Connection", "Color fibers based on their connection." );
634  fibers->setSelectedColorScheme( 3 );
635  m_fiberOutput->updateData( fibers );
636 }
637 
639 {
640  return m_connectorData;
641 }
642 
644 {
645  return m_fiberHandler;
646 }
647 
649 {
650  m_connectorData->deselectPoint();
651  m_fiberHandler->addVerticesToFiber( std::vector< osg::Vec3 >( m_prediction.begin(), m_prediction.end() ), m_fiberHandler->getSelectedFiber() );
652  m_fiberHandler->selectLastPoint();
653  updateAll();
654 }
655 
656 void WMPointConnector::handleClickSelection( bool clickType, double x, double y )
657 {
658  osg::Camera* camera = WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getCamera();
659  osg::Matrix VP = camera->getViewMatrix() * camera->getProjectionMatrix();
660 
661  osg::Matrix inverseVP;
662  inverseVP.invert( VP );
663 
664  osg::Vec3 nearPoint( x, y, -1.0f );
665  osg::Vec3 farPoint( x, y, 1.0f );
666  nearPoint = nearPoint * inverseVP;
667  farPoint = farPoint * inverseVP;
668 
669  osg::Vec3 direction = farPoint - nearPoint;
670  direction.normalize();
671 
672  handleClick( nearPoint, direction, clickType );
673 }
674 
675 void WMPointConnector::pushEventQueue( std::function< void() > func )
676 {
677  std::unique_lock< std::mutex > lock( m_eventMutex );
678  m_eventQueue.push_back( func );
679  m_eventCondition->notify();
680 }
681 
682 void WMPointConnector::handleLeftSelection( std::vector< WPosition > positions )
683 {
684  for( auto vertex = positions.begin(); vertex != positions.end(); )
685  {
686  if( m_fiberHandler->getFiberOfPoint( *vertex ) || m_fiberHandler->isPointHidden( *vertex ) || isAdaptivelyHidden( *vertex ) )
687  {
688  positions.erase( vertex );
689  }
690  else
691  {
692  vertex++;
693  }
694  }
695  if( m_enableSAPT->get() )
696  {
697  auto start = std::chrono::high_resolution_clock::now();
698  size_t amount = positions.size();
699 
700  positions = WAngleHelper::findSmoothestPath( positions, m_fiberHandler->getFibers()->at( m_fiberHandler->getSelectedFiber() ) );
701 
702  auto end = std::chrono::high_resolution_clock::now();
703  std::chrono::duration< double > elapsed = end - start;
704  wlog::debug( "PointConnector" ) << "SAPT " << amount << " points in " << elapsed.count() << " seconds";
705  }
706 
707  if( positions.empty() )
708  {
709  return;
710  }
711  m_connectorData->deselectPoint();
712  m_fiberHandler->addVerticesToFiber( std::vector< osg::Vec3 >( positions.begin(), positions.end() ), m_fiberHandler->getSelectedFiber() );
713  m_fiberHandler->selectLastPoint();
714  updateAll();
715 }
716 
717 void WMPointConnector::handleRightSelection( std::vector< WPosition > positions )
718 {
719  size_t idx = 0;
720  size_t fibIdx = m_fiberHandler->getSelectedFiber();
721  for( auto vertex = positions.begin(); vertex != positions.end(); )
722  {
723  if( m_fiberHandler->getFiberOfPoint( *vertex, &idx ) && idx == fibIdx )
724  {
725  vertex++;
726  }
727  else
728  {
729  positions.erase( vertex );
730  }
731  }
732 
733  if( positions.empty() )
734  {
735  return;
736  }
737  m_connectorData->deselectPoint();
738  m_fiberHandler->removeVerticesFromFiber( std::vector< osg::Vec3 >( positions.begin(), positions.end() ), fibIdx );
739  m_fiberHandler->selectLastPoint();
740  updateAll();
741 }
742 
744 {
745  if( !m_onscreenSelection->hasMoved() )
746  {
747  // no movement do raycast.
748  float mouseX = x * 2.0 - 1.0;
749  float mouseY = y * 2.0 - 1.0;
750 
751  pushEventQueue( std::bind( &WMPointConnector::handleClickSelection, this, m_onscreenSelection->getClickType(), mouseX, mouseY ) );
752  return;
753  }
754 
755  std::vector< WPosition > toCheck;
756  for( size_t idx = 0; idx < m_connectorData->getVertices()->size(); idx++ )
757  {
758  osg::Vec3 vertex = m_connectorData->getVertices()->at( idx );
759  toCheck.push_back( WPosition( vertex.x() * m_scaling->get().x(), vertex.y() * m_scaling->get().y(), vertex.z() * m_scaling->get().z() ) );
760  }
761 
762  toCheck = m_onscreenSelection->isSelected( toCheck );
763  if( toCheck.empty() )
764  {
765  return;
766  }
767 
768  std::vector< WPosition > positions;
769  for( size_t idx = 0; idx < toCheck.size(); idx++ )
770  {
771  WPosition vertex = toCheck.at( idx );
772  vertex = WPosition( vertex.x() / m_scaling->get().x(), vertex.y() / m_scaling->get().y(), vertex.z() / m_scaling->get().z() );
773  positions.push_back( vertex );
774  }
775 
776  if( m_onscreenSelection->getClickType() )
777  {
778  pushEventQueue( std::bind( &WMPointConnector::handleLeftSelection, this, positions ) );
779  }
780  else
781  {
782  pushEventQueue( std::bind( &WMPointConnector::handleRightSelection, this, positions ) );
783  }
784 }
785 
786 std::shared_ptr< WOnscreenSelection > WMPointConnector::getOnscreenSelection()
787 {
788  return m_onscreenSelection;
789 }
790 
792 {
793  return m_scaling;
794 }
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
std::shared_ptr< WCondition > SPtr
Shared pointer type for WCondition.
Definition: WCondition.h:48
Holds the data of the WMPointConnector.
std::shared_ptr< WConnectorData > SPtr
A shared_ptr to this class.
Represents a simple set of WFibers.
std::shared_ptr< WDataSetFibers > SPtr
Pointer to dataset.
Dataset to store a bunch of points without order or topology.
std::shared_ptr< WDataSetPoints > SPtr
Pointer to dataset.
std::shared_ptr< std::vector< float > > VertexArray
List of vertex coordinates in term of components of vertices.
Handles the fibers of the WMPointsConnector.
Definition: WFiberHandler.h:48
std::vector< osg::Vec3 > PCFiber
Vector of 3D vectors, representing points.
Definition: WFiberHandler.h:63
std::shared_ptr< PCFiberList > PCFiberListSPtr
Shared pointer to fibers-vector.
Definition: WFiberHandler.h:73
std::shared_ptr< WFiberHandler > SPtr
A shared_ptr to this class.
Definition: WFiberHandler.h:53
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
The keyboard handler for the keyboard events of WMPointConnector.
This module connects the points in a point dataset.
WModule::SPtr m_fiberDisplay
The WMFiberDisplay associated with this module.
std::shared_ptr< std::vector< size_t > > SPSizeVector
represents a std::shared_ptr to a vector containing a vector of size_t.
virtual void activate()
Deactivates or activates the inner modules when active changes.
WPropDouble m_adaptiveVisibilityAngle
Property to set the angle for the adaptive visibility.
bool isAdaptivelyHidden(osg::Vec3 vertex, osg::Vec3 *from=NULL)
Checks whether a vertex is adaptively hidden.
virtual void properties()
Initialize the properties for this module.
std::shared_ptr< WConnectorData > m_connectorData
The data of this module.
void updateAll()
Updates all.
WPropDouble m_hiddenOpacity
Property to set the opacity of the hidden points.
WPropPosition m_scaling
Property for the scaling as Vector.
WMPointConnector()
Constructor.
std::vector< std::function< void() > > m_eventQueue
A vector for the events.
virtual ~WMPointConnector()
Destructor.
std::shared_ptr< WOnscreenSelection > getOnscreenSelection()
float hitVertex(osg::Vec3 rayStart, osg::Vec3 rayDir, osg::Vec3 vertex, float radius)
Checks if a vertex with a certain radius is hit by a ray.
WPropBool m_enableAdaptiveVisibility
Property to enable adaptive visibility.
WPropPosition getScaling()
void handleInput()
Handles the input of this module.
bool findClickedPoint(osg::Vec3 cameraPosition, osg::Vec3 direction, size_t *hitIdx)
Finds the point that was clicked and writes it into hitIdx, while return whether a point was hit.
void pushEventQueue(std::function< void() > func)
Pushes a function to the selection queue.
void createHandler()
Creates the WKeyboardHandler and registers them.
std::shared_ptr< WModuleOutputData< WDataSetFibers > > m_fiberOutput
An output connector used to provide fibers to other modules.
void handleRightSelection(std::vector< WPosition > positions)
Handles the selection of a right click.
std::mutex m_eventMutex
A mutex for the vector to make it thread-safe.
virtual void connectors()
Initialize the connectors this module is using.
std::shared_ptr< WFiberHandler > getFiberHandler()
WModule::SPtr m_pointRenderer
The WMPointRenderer associated with this module.
void acceptPrediction()
Accepts the current prediction.
std::shared_ptr< WConnectorData > getConnectorData()
WPropBool m_enableSizes
Property to enable the sizes.
virtual void moduleMain()
Entry point after loading the module.
osg::ref_ptr< WKeyboardHandler > m_keyboardHandler
The keyboard handler for this point connector.
virtual const std::string getDescription() const
Gives back a description of this module.
std::shared_ptr< std::vector< float > > SPFloatVector
represents a std::shared_ptr to a vector containing a vector of floats.
std::vector< WPosition > m_prediction
The current prediction.
std::shared_ptr< WModuleInputData< WDataSetPoints > > m_pointInput
An input connector used to get points from other modules.
void createPrediction()
Creates a track continuation prediction.
void toggleActivationOfModule(WModule::SPtr mod)
Toggles the activation of a module.
void handleClickSelection(bool clickType, double x, double y)
Handles a selection with only one click.
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 selectionEnd(WOnscreenSelection::WSelectionType type, float x, float y)
The end callback of m_onscreenSelection.
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
void createFiberDisplay()
Creates the WMFiberDisplay and runs it.
void updateOutput()
Updates the fiber output.
std::shared_ptr< WModuleOutputData< WDataSetPoints > > m_pointOutput
The internal pointOutput to pass data to the WMPointRenderer.
std::shared_ptr< WFiberHandler > m_fiberHandler
The WFiberHandler of this module.
WCondition::SPtr m_eventCondition
A condition notifying when something was added to the event queue.
void updatePoints()
Redraws the current vertices with their colors.
WPropBool m_enableSAPT
Property to enable the adjusted dijkstra.
void handleLeftSelection(std::vector< WPosition > positions)
Handles the selection of a left click.
virtual const std::string getName() const
Gives back the name of this module.
void handleClick(osg::Vec3 cameraPosition, osg::Vec3 direction, bool isLeftClick)
Handles a click on the drawing area.
void createPointRenderer()
Creates the WMPointRenderer and runs it.
std::shared_ptr< WOnscreenSelection > m_onscreenSelection
Enables possibility for multiselection of points.
WPropBool m_enablePrediction
Enables the prediction.
Class able to contain other modules.
virtual WModule::SPtr createAndAdd(std::string name)
Convenience method to create a module instance with a given name and automatically add it to the cont...
virtual void stop()
Stops all modules inside this container.
static PtrType createAndAdd(std::shared_ptr< WModule > module, std::string name="", std::string description="")
Convenience method to create a new instance of this in data connector with proper type and add it to ...
static PtrType createAndAdd(std::shared_ptr< WModule > module, std::string name="", std::string description="")
Convenience method to create a new instance of this out data connector with proper type and add it to...
static PtrType create(std::shared_ptr< WModule > module, std::string name="", std::string description="")
Convenience method to create a new instance of this out data connector with proper type.
std::shared_ptr< WModule > SPtr
Shared pointer to a WModule.
Definition: WModule.h:106
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 removeConnectors()
Removes all connectors properly.
Definition: WModule.cpp:194
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
std::shared_ptr< WProgressCombiner > m_progress
Progress indicator used as parent for all progress' of this module.
Definition: WModule.h:652
virtual void connectors()
Initialize connectors in this function.
Definition: WModule.cpp:208
Manages different types of selection.
WSelectionType
The different types of selection.
This only is a 3d double vector.
Class managing progress inside of modules.
Definition: WProgress.h:42
std::shared_ptr< WPropertyGroup > SPtr
shared pointer to object of this type
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.
Base Class for all value set types.
Definition: WValueSet.h:47
std::vector< WPosition > findSmoothestPath(std::vector< WPosition > positions)
Determines the path with the smallest angle change.
double calculateAngle(WPosition a, WPosition b)
Calculates the angle between two positions.
WStreamedLogger debug(const std::string &source)
Logging a debug message.
Definition: WLogger.h:331