//--------------------------------------------------------------------------- // // 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 . // //--------------------------------------------------------------------------- #include #include #include "WClickHandler.h" #include "WConnectorData.h" #include "WFiberHandler.h" #include "WMPointConnector.h" #include "WKeyboardHandler.h" static const osg::Vec4 COLOR_SEL_POINT( 255.0 / 255.0, 190.0 / 255.0, 7.0 / 255.0, 1.0 ); static const osg::Vec4 COLOR_SEL_FIBER( 30.0 / 255.0, 136.0 / 255.0, 229.0 / 255.0, 1.0 ); W_LOADABLE_MODULE( WMPointConnector ) WMPointConnector::WMPointConnector(): WModuleContainer() { m_connectorData = WConnectorData::SPtr( new WConnectorData() ); m_fiberHandler = WFiberHandler::SPtr( new WFiberHandler( this ) ); } WMPointConnector::~WMPointConnector() { removeConnectors(); } boost::shared_ptr< WModule > WMPointConnector::factory() const { return boost::shared_ptr< WModule >( new WMPointConnector() ); } const char** WMPointConnector::getXPMIcon() const { return NULL; } const std::string WMPointConnector::getName() const { return "Point Connector"; } const std::string WMPointConnector::getDescription() const { return "Allows user to manually connect points to fibers."; } void WMPointConnector::connectors() { m_pointInput = WModuleInputData< WDataSetPoints >::createAndAdd( shared_from_this(), "points in", "The data to display" ); m_pointAndFibersOutput = WModuleOutputData< WDataSetPointsAndFibers >::createAndAdd( shared_from_this(), "points and fibers out", "Contains the internal points and the connected fibers " ); m_pointOutput = WModuleOutputData< WDataSetPoints >::create( shared_from_this(), "points out", "The data that is passed internally" ); m_fiberOutput = WModuleOutputData< WDataSetFibers >::create( shared_from_this(), "fibers out", "The created fibers" ); WModule::connectors(); } void WMPointConnector::properties() { m_fiberHandler->createProperties( m_properties ); WModule::properties(); } void WMPointConnector::moduleMain() { m_moduleState.setResetable( true, true ); m_moduleState.add( m_pointInput->getDataChangedCondition() ); createPointRenderer(); createFiberDisplay(); createHandler(); ready(); while( !m_shutdownFlag() ) { debugLog() << "Waiting ..."; m_moduleState.wait(); if( m_shutdownFlag() ) { break; } handleInput(); } stop(); } void WMPointConnector::activate() { m_pointRenderer->getProperties()->getProperty( "active" )->toPropBool()->set( m_active->get() ); m_fiberDisplay->getProperties()->getProperty( "active" )->toPropBool()->set( m_active->get() ); } void WMPointConnector::createPointRenderer() { WPropertyGroup::SPtr pointGroup = m_properties->addPropertyGroup( "Point Renderer", "Properties passed through from the point renderer" ); m_pointRenderer = createAndAdd( "Point Renderer" ); m_pointRenderer->isReady().wait(); m_pointOutput->connect( m_pointRenderer->getInputConnector( "points" ) ); pointGroup->addProperty( "Activate", "Activates the point renderer", true, boost::bind( &WMPointConnector::toggleActivationOfModule, this, m_pointRenderer ) ); pointGroup->addProperty( m_pointRenderer->getProperties()->getProperty( "Point size" ) ); } void WMPointConnector::createFiberDisplay() { WPropertyGroup::SPtr fiberGroup = m_properties->addPropertyGroup( "Fiber Display", "Properties passed through from the fiber display" ); m_fiberDisplay = createAndAdd( "Fiber Display" ); m_fiberDisplay->isReady().wait(); m_fiberOutput->connect( m_fiberDisplay->getInputConnector( "fibers" ) ); fiberGroup->addProperty( "Activate", "Activates the fiber display", true, boost::bind( &WMPointConnector::toggleActivationOfModule, this, m_fiberDisplay ) ); fiberGroup->addProperty( m_fiberDisplay->getProperties()->getProperty( "Line Rendering" )->toPropGroup()->getProperty( "Line width" ) ); } void WMPointConnector::toggleActivationOfModule( WModule::SPtr mod ) { WPropBool active = mod->getProperties()->getProperty( "active" )->toPropBool(); active->set( !active->get() ); } void WMPointConnector::createHandler() { osg::ref_ptr< osgViewer::View > viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getView(); osg::ref_ptr< WClickHandler > clickHandler = new WClickHandler( this ); viewer->addEventHandler( clickHandler.get() ); osg::ref_ptr< WKeyboardHandler > keyboardHandler = new WKeyboardHandler( this ); viewer->addEventHandler( keyboardHandler.get() ); } void WMPointConnector::handleInput() { WDataSetPoints::SPtr points = m_pointInput->getData(); if( !points ) { debugLog() << "Invalid Data. Break."; return; } WDataSetPointsAndEventID::SPtr pointsAndEventIDs = boost::dynamic_pointer_cast< WDataSetPointsAndEventID >( points ); m_connectorData->clear(); m_fiberHandler->clear(); WFiberHandler::PCFiberListSPtr fibers = m_fiberHandler->getFibers(); for( size_t pointIdx = 0; pointIdx < points->size(); ++pointIdx ) { osg::Vec3 vertex = points->operator[]( pointIdx ); m_connectorData->addVertex( vertex, points->getColor( pointIdx ) ); if( pointsAndEventIDs ) { int eventID = pointsAndEventIDs->getEventID( pointIdx ); while( fibers->size() <= eventID ) { m_fiberHandler->addFiber( "Track " + boost::lexical_cast< std::string >( fibers->size() ), true, false ); } ( fibers->begin() + eventID )->push_back( vertex ); } } for( size_t idx = fibers->size() - 1; idx > 0; idx--) { if( fibers->at( idx ).size() <= 1 ) { m_fiberHandler->removeFiber( idx, true, false ); } } m_fiberHandler->setFiberCount( fibers->size() ); m_fiberHandler->selectorUpdate( fibers->size() - 1 ); m_fiberHandler->sortVertices(); updatePoints(); updateOutput(); } void WMPointConnector::updatePoints() { if( m_pointRenderer == NULL ) { return; } if( m_connectorData->getVertices()->size() == 0 ) { m_pointOutput->updateData( NULL ); return; } WDataSetPoints::VertexArray vertices( new std::vector< float > ); WDataSetPoints::VertexArray colors( new std::vector< float > ); for( size_t idx = 0; idx < m_connectorData->getVertices()->size(); idx++ ) { osg::Vec3 vertex = m_connectorData->getVertices()->at( idx ); osg::Vec4 color( 1.0, 1.0, 1.0, 1.0 ); vertices->push_back( vertex.x() ); vertices->push_back( vertex.y() ); vertices->push_back( vertex.z() ); size_t tmpIdx; if( m_connectorData->getSelectedPoint( &tmpIdx ) && tmpIdx == idx ) { color = COLOR_SEL_POINT; } else if( m_fiberHandler->getFiberOfPoint( vertex, &tmpIdx ) && m_fiberHandler->getSelectedFiber() == tmpIdx ) { color = COLOR_SEL_FIBER; } if( m_fiberHandler->isPointHidden( vertex ) ) { color[3] = 0.1; } colors->push_back( color.x() ); colors->push_back( color.y() ); colors->push_back( color.z() ); colors->push_back( color.w() ); } m_pointOutput->updateData( WDataSetPoints::SPtr( new WDataSetPoints( vertices, colors ) ) ); } void WMPointConnector::handleClick( osg::Vec3 cameraPosition, osg::Vec3 direction, bool isLeftClick ) { size_t hitIdx = 0; if( findClickedPoint( cameraPosition, direction, &hitIdx ) ) { if( isLeftClick ) { size_t fiberIdx = 0; if( m_fiberHandler->getFiberOfPoint( m_connectorData->getVertices()->at( hitIdx ), &fiberIdx ) ) { if( m_fiberHandler->getSelectedFiber() == fiberIdx ) { m_connectorData->selectPoint( hitIdx ); } else { m_fiberHandler->selectFiber( fiberIdx ); m_fiberHandler->selectorUpdate( fiberIdx ); } } else { m_connectorData->deselectPoint(); m_connectorData->selectPoint( hitIdx ); m_fiberHandler->addVertexToFiber( m_connectorData->getVertices()->at( hitIdx ), m_fiberHandler->getSelectedFiber() ); } } else { m_connectorData->deselectPoint(); m_fiberHandler->removeVertexFromFiber( m_connectorData->getVertices()->at( hitIdx ), m_fiberHandler->getSelectedFiber() ); m_fiberHandler->selectLastPoint(); } updatePoints(); updateOutput(); } } bool WMPointConnector::findClickedPoint( osg::Vec3 cameraPosition, osg::Vec3 direction, size_t* hitIdx ) { bool hasHit = false; float distance = 0; float size = m_pointRenderer->getProperties()->getProperty( "Point size" )->toPropDouble()->get(); for( size_t idx = 0; idx < m_connectorData->getVertices()->size(); idx++ ) { osg::Vec3 vertex = m_connectorData->getVertices()->at( idx ); float hit = hitVertex( cameraPosition, direction, vertex, size ); if( hit > 0.0 ) { float dis = ( vertex - cameraPosition ).length2(); if( !hasHit ) { hasHit = true; distance = dis; *hitIdx = idx; } else if( dis < distance ) { distance = dis; *hitIdx = idx; } } } return hasHit; } float WMPointConnector::hitVertex( osg::Vec3 rayStart, osg::Vec3 rayDir, osg::Vec3 vertex, float radius ) { osg::Vec3 oc = rayStart - vertex; float a = rayDir * rayDir; float b = 2.0 * ( oc * rayDir ); float c = ( oc * oc ) - radius * radius; float discriminant = b * b - 4 * a * c; if( discriminant < 0.0 ) { return -1.0; } else if( discriminant == 0.0 ) { return 0.0; } else { float sqrtDis = sqrt( discriminant ); float numerator = -b - sqrtDis; if( numerator > 0.0 ) { return numerator / ( 2.0 * a ); } numerator = -b + sqrtDis; if( numerator > 0.0 ) { return numerator / ( 2.0 * a ); } else { return -1.0; } } } void WMPointConnector::updateOutput() { if( m_fiberDisplay == NULL ) { return; } boost::shared_ptr< std::vector< float > > vertices = boost::shared_ptr< std::vector< float > >( new std::vector< float >() ); boost::shared_ptr< std::vector< float > > colors = boost::shared_ptr< std::vector< float > >( new std::vector< float >() ); boost::shared_ptr< std::vector< size_t > > lineStartIndexes = boost::shared_ptr< std::vector< size_t > >( new std::vector< size_t >() ); boost::shared_ptr< std::vector< size_t > > lineLength = boost::shared_ptr< std::vector< size_t > >( new std::vector< size_t >() ); boost::shared_ptr< std::vector< size_t > > verticesReverse = boost::shared_ptr< std::vector< size_t > >( new std::vector< size_t >() ); for( size_t idx = 0; idx < m_fiberHandler->getFibers()->size(); idx++ ) { WFiberHandler::PCFiber fiber = m_fiberHandler->getFibers()->at( idx ); lineStartIndexes->push_back( vertices->size() / 3 ); lineLength->push_back( fiber.size() ); osg::Vec4 color( 0.0, 0.0, 0.0, 1.0 ); if( m_fiberHandler->getSelectedFiber() == idx ) { color = COLOR_SEL_FIBER; } if( m_fiberHandler->isHidden( idx ) ) { color[3] = 0.1; } for( size_t vIdx = 0; vIdx < fiber.size(); vIdx++ ) { osg::Vec3 vertex = fiber[vIdx]; vertices->push_back( vertex.x() ); vertices->push_back( vertex.y() ); vertices->push_back( vertex.z() ); colors->push_back( color.x() ); colors->push_back( color.y() ); colors->push_back( color.z() ); colors->push_back( color.w() ); verticesReverse->push_back( idx ); } } WDataSetFibers::SPtr fibers( new WDataSetFibers( vertices, lineStartIndexes, lineLength, verticesReverse ) ); if( vertices->size() == 0 ) { m_fiberOutput->updateData( NULL ); return; } fibers->addColorScheme( colors, "Connection", "Color fibers based on their connection." ); fibers->setSelectedColorScheme( 3 ); m_fiberOutput->updateData( fibers ); m_pointAndFibersOutput->updateData( boost::shared_ptr< WDataSetPointsAndFibers >( new WDataSetPointsAndFibers( m_pointOutput->getData(), m_fiberOutput->getData() ) ) ); } WConnectorData::SPtr WMPointConnector::getConnectorData() { return m_connectorData; } WFiberHandler::SPtr WMPointConnector::getFiberHandler() { return m_fiberHandler; }