Commit f043bb7f authored by Alexander Wiebel's avatar Alexander Wiebel

[ADD] employ Dijkstra from boost for VisiTrace

parent 32529bf0
......@@ -50,7 +50,7 @@
#include "WMPickingDVRHelper.h"
#include "WVisiTrace.h"
//Module Defines
// Module Defines
#define WMPICKINGDVR_MAX_INT "Picking - Maximum Intensity"
#define WMPICKINGDVR_FIRST_HIT "Picking - First Hit"
#define WMPICKINGDVR_THRESHOLD "Picking - Threshold"
......
......@@ -22,12 +22,18 @@
//
//---------------------------------------------------------------------------
#include <string>
#include <utility>
#include <vector>
#include "core/common/math/linearAlgebra/WPosition.h"
#include "core/common/WAssert.h"
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/property_map/property_map.hpp>
#include "WVisiTrace.h"
WVisiTrace::WVisiTrace():
......@@ -95,9 +101,140 @@ std::vector< std::vector< int > > WVisiTrace::getInverseLinearizedNodesRefs() co
return inverseRefs;
}
void WVisiTrace::performDijkstra()
{
//using namespace boost;
typedef boost::adjacency_list< boost::listS, boost::vecS, boost::directedS,
boost::no_property, boost::property< boost::edge_weight_t, double > > graph_t;
typedef boost::graph_traits< graph_t >::vertex_descriptor vertex_descriptor;
typedef std::pair<int, int> Edge;
std::vector< std::pair< int, int > > linearized = getLinearizedNodesRefs();
std::vector< std::vector< int > > linearizedInverse = getInverseLinearizedNodesRefs();
const int numVirtNodes = 2; // virtual start an end nodes
const int startNodeId = 0;
const int endNodeId = 1;
const int num_nodes = linearized.size() + numVirtNodes;
std::vector< std::string > name( 0 );
name.push_back( "Start" );
name.push_back( "End" );
for( int id = 0; id < num_nodes; ++id )
{
name.push_back( std::to_string( id + numVirtNodes ) );
}
std::vector< Edge > edgeVector( 0 );
std::vector< double > weightsV( 0 );
// Edges from virtual start node to candidates of first ray
for( auto candi : linearizedInverse[0] )
{
edgeVector.push_back( Edge( startNodeId, candi + numVirtNodes ) );
weightsV.push_back( 1 );
}
// Edges from candidates of one ray to those of the next ray
for( size_t rayId = 0; rayId < linearizedInverse.size() - 1; ++rayId )
{
for( size_t firstId = 0; firstId < linearizedInverse[rayId].size(); ++firstId )
{
for( size_t secondId = 0; secondId < linearizedInverse[rayId+1].size(); ++secondId )
{
edgeVector.push_back( Edge( linearizedInverse[rayId][firstId] + numVirtNodes,
linearizedInverse[rayId+1][secondId] + numVirtNodes ) );
WPosition firstPos = m_candidatePositions[rayId][firstId];
WPosition secondPos = m_candidatePositions[rayId+1][secondId];
double distance = length( firstPos - secondPos );
weightsV.push_back( distance );
}
}
}
// Edges from candidates of last ray to virtual end node
for( auto candi : linearizedInverse[linearizedInverse.size()-1] )
{
edgeVector.push_back( Edge( candi + numVirtNodes, endNodeId ) );
weightsV.push_back( 1 );
}
Edge* edge_array = &edgeVector[0];
double* weights = &weightsV[0];
int num_arcs = edgeVector.size();
graph_t g( edge_array, edge_array + num_arcs, weights, num_nodes );
//property_map<graph_t, edge_weight_t>::type weightmap = get(edge_weight, g);
std::vector<vertex_descriptor> p( num_vertices( g ) );
std::vector<double> distResult( num_vertices( g ) );
vertex_descriptor s = vertex( startNodeId, g );
dijkstra_shortest_paths( g,
s,
predecessor_map( boost::make_iterator_property_map( p.begin(), get( boost::vertex_index, g ) ) ).
distance_map( boost::make_iterator_property_map( distResult.begin(), get( boost::vertex_index, g ) ) ) );
std::vector< int > shortestPathIds( 0 );
int parentId = endNodeId;
shortestPathIds.push_back( parentId );
while( parentId != startNodeId )
{
parentId = p[parentId];
shortestPathIds.push_back( parentId );
}
std::reverse( shortestPathIds.begin(), shortestPathIds.end() );
for( size_t id = 1; id < shortestPathIds.size() - 1; ++id )
{
int rayId = linearized[shortestPathIds[id]-numVirtNodes].first;
int candidateId = linearized[shortestPathIds[id]-numVirtNodes].second;
m_curve3D.push_back( m_candidatePositions[rayId][candidateId] );
}
// DEBUGGING: writing solution to file and stdout
// {
// #include <iostream>
// #include <fstream>
// std::cout << "distances and parents:" << std::endl;
// std::cout << "distance(" << "END" << ") = " << distResult[endNodeId] << std::endl;
// std::cout << "distances and parents:" << std::endl;
// graph_traits < graph_t >::vertex_iterator vi, vend;
// for (boost::tie(vi, vend) = vertices(g); vi != vend; ++vi)
// {
// std::cout << "distance(" << name[*vi] << ") = " << distResult[*vi] << ", ";
// std::cout << "parent(" << name[*vi] << ") = " << name[p[*vi]] << std::endl;
// }
// std::cout << std::endl;
// std::ofstream dot_file("/tmp/dijkstra-eg.dot");
// dot_file << "digraph D {\n"
// << " rankdir=LR\n"
// << " size=\"20,20\"\n"
// << " ratio=\"fill\"\n"
// << " edge[style=\"bold\"]\n" << " node[shape=\"circle\"]\n";
// graph_traits < graph_t >::edge_iterator ei, ei_end;
// for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
// graph_traits < graph_t >::edge_descriptor e = *ei;
// graph_traits < graph_t >::vertex_descriptor
// u = source(e, g), v = target(e, g);
// dot_file << name[u] << " -> " << name[v]
// << "[label=\"" << get(weightmap, e) << "\"";
// if (p[v] == u)
// dot_file << ", color=\"black\"";
// else
// dot_file << ", color=\"grey\"";
// dot_file << "]";
// }
// dot_file << "}";
// }
}
void WVisiTrace::performVisiTrace()
{
WAssert( false, "Not yet implemented" );
performDijkstra();
}
void WVisiTrace::reset()
......
......@@ -90,6 +90,11 @@ private:
*/
std::vector< std::vector< int > > getInverseLinearizedNodesRefs() const;
/**
* Create weighted graph and find shortest path from according to VisiTrace.
*/
void performDijkstra();
std::vector< std::vector< WPosition > > m_candidatePositions; //!< The candidate positions for all rays
std::vector< std::vector< double > > m_candidateJumps; //!< The opacity jumps belonging to the intervals of the candidate positions.
std::vector< WPosition > m_curve3D; //!< The 3D curve computed by VisiTrace.
......
......@@ -31,6 +31,7 @@
#include <cxxtest/TestSuite.h>
#include "../WVisiTrace.h"
#include "../../../core/common/math/test/WPositionTraits.h"
/**
* Test for WMWriteMesh
......@@ -46,7 +47,7 @@ public:
}
/**
* Ensure instatiation does not throw and does initialization right.
* Ensure instantiation does not throw and does initialization right.
*/
void testInstatiation()
{
......@@ -70,7 +71,7 @@ public:
{
WVisiTrace myVisiTrace;
std::vector< std::vector< WPosition > > candidates;
const std::vector< int > sizes = { 2, 4, 5, 8, 3, 6 };
const std::vector< int > sizes = { 4, 2, 5, 8, 3, 6 };
for( size_t id = 0; id < sizes.size(); ++id )
{
myVisiTrace.m_candidatePositions.push_back( std::vector< WPosition >( sizes[id] ) );
......@@ -82,10 +83,10 @@ public:
TS_ASSERT_EQUALS( order[0], std::make_pair( 0, 0 ) );
TS_ASSERT_EQUALS( order[1], std::make_pair( 0, 1 ) );
TS_ASSERT_EQUALS( order[2], std::make_pair( 1, 0 ) );
TS_ASSERT_EQUALS( order[3], std::make_pair( 1, 1 ) );
TS_ASSERT_EQUALS( order[2], std::make_pair( 0, 2 ) );
TS_ASSERT_EQUALS( order[3], std::make_pair( 0, 3 ) );
TS_ASSERT_EQUALS( order[5], std::make_pair( 1, 3 ) );
TS_ASSERT_EQUALS( order[5], std::make_pair( 1, 1 ) );
TS_ASSERT_EQUALS( order[6], std::make_pair( 2, 0 ) );
TS_ASSERT_EQUALS( order[27], std::make_pair( 5, 5 ) );
......@@ -98,7 +99,7 @@ public:
{
WVisiTrace myVisiTrace;
std::vector< std::vector< WPosition > > candidates;
const std::vector< int > sizes = { 2, 4, 5, 8, 3, 6 };
const std::vector< int > sizes = { 4, 2, 5, 8, 3, 6 };
for( size_t id = 0; id < sizes.size(); ++id )
{
myVisiTrace.m_candidatePositions.push_back( std::vector< WPosition >( sizes[id] ) );
......@@ -110,16 +111,50 @@ public:
TS_ASSERT_EQUALS( inverseRefs[0][0], 0 );
TS_ASSERT_EQUALS( inverseRefs[0][1], 1 );
TS_ASSERT_EQUALS( inverseRefs[0][2], 2 );
TS_ASSERT_EQUALS( inverseRefs[0][3], 3 );
TS_ASSERT_EQUALS( inverseRefs[1][0], 2 );
TS_ASSERT_EQUALS( inverseRefs[1][1], 3 );
TS_ASSERT_EQUALS( inverseRefs[1][2], 4 );
TS_ASSERT_EQUALS( inverseRefs[1][3], 5 );
TS_ASSERT_EQUALS( inverseRefs[1][0], 4 );
TS_ASSERT_EQUALS( inverseRefs[1][1], 5 );
TS_ASSERT_EQUALS( inverseRefs[2][0], 6 );
TS_ASSERT_EQUALS( inverseRefs[5][5], 27 );
}
/**
* Check throwing of Dijkstra
*/
void testPerformDijkstraException()
{
WVisiTrace myVisiTrace;
myVisiTrace.m_candidatePositions.push_back(
{
WPosition( 1, 0, 0 ),
WPosition( 1, 0, 1 ),
WPosition( 1, 0, 2 ),
WPosition( 1, 0, 3 )
}
);
myVisiTrace.m_candidatePositions.push_back(
{
WPosition( 1, 1, -3.5 ),
WPosition( 1, 1, -2.5 )
} );
myVisiTrace.m_candidatePositions.push_back(
{
WPosition( 1, 1.2, 0 ),
WPosition( 1, 1.2, 1 ),
WPosition( 1, 1.2, 2 ),
WPosition( 1, 1.2, 3 )
}
);
TS_ASSERT_THROWS_NOTHING( myVisiTrace.performDijkstra() );
TS_ASSERT_EQUALS( myVisiTrace.m_curve3D[0], WPosition( 1, 0, 0 ) );
TS_ASSERT_EQUALS( myVisiTrace.m_curve3D[0], WPosition( 1, 0, 0 ) );
}
};
#endif // WVISITRACE_TEST_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment