/*
Copyright (C) 2015
Matthias P. Braendli, matthias.braendli@mpb.li
http://opendigitalradio.org
*/
/*
This file is part of ODR-DPD.
ODR-DPD is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
ODR-DPD 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with ODR-DPD. If not, see .
*/
#include "pointcloud.hpp"
#include
#include
#include
#include
#include
#include
using namespace std;
PointCloud::PointCloud(size_t num_points) :
m_num_points(num_points),
m_rxgain(1.0),
m_txgain(1.0)
{
SDL_Init(SDL_INIT_VIDEO);
atexit(SDL_Quit);
SDL_WM_SetCaption("Point Cloud", NULL);
SDL_SetVideoMode(720,640, 32, SDL_OPENGL);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(6,(double)640/480,1,1000);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
}
// Not really a border, but you get the idea
vector PointCloud::generate_border(void)
{
vector points(4);
points[0].x = 0;
points[0].y = 0;
points[1].x = 1;
points[1].y = 0;
points[2].x = 0;
points[2].y = 1;
points[3].x = 1;
points[3].y = 1;
for (auto &p : points) {
p.r = 255;
p.g = 255;
p.b = 0;
}
return points;
}
void PointCloud::push_samples(std::pair, std::vector > &data)
{
auto &rx = data.first;
auto &tx = data.second;
if (rx.size() != tx.size()) {
throw std::runtime_error("RX and TX have different size");
}
std::lock_guard lock(m_mutex);
for (size_t i = 0; i < rx.size(); i++) {
Point p;
// Magnitude is position
p.x = std::abs(tx[i]) * m_txgain;
p.y = std::abs(rx[i]) * m_rxgain;
p.z = 0.0;
double arg_rx = std::arg(rx[i]);
double arg_tx = std::arg(tx[i]);
// Phase is colour
p.r = p.b = 255;
p.g = 64;
if (arg_rx > arg_tx) {
int corr = 255 - 20 * (arg_rx - arg_tx);
if (corr < 0) {
corr = 0;
}
p.r = corr;
}
else {
int corr = 255 - 20 * (arg_tx - arg_rx);
if (corr < 0) {
corr = 0;
}
p.b = corr;
}
m_points.push_back(p);
}
if (m_points.size() > m_num_points + rx.size()) {
m_points.erase(m_points.begin(), m_points.begin() + rx.size());
}
}
std::string PointCloud::handle_event()
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch(event.type){
case SDL_QUIT:
throw sdl_quit();
break;
case SDL_KEYDOWN:
std::string key(SDL_GetKeyName(event.key.keysym.sym));
return key;
break;
}
}
return std::string();
}
void PointCloud::draw()
{
std::lock_guard lock(m_mutex);
size_t num_points_drawn = std::min(m_num_points, m_points.size());
vector v(m_num_points);
for (size_t i = 0; i < num_points_drawn; i++) {
v[i] = m_points[i];
}
m_mutex.unlock();
vector border = generate_border();
v.insert(v.end(), border.begin(), border.end());
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushMatrix();
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
0.5,0.5,10,
0.5,0.5,0,
0,1,0);
glPointSize(3.0);
glBegin(GL_POINTS);
for (size_t n = 0; n < v.size(); n++){
glColor4ub(v[n].r, v[n].g, v[n].b, 50);
glVertex3d(v[n].x, v[n].y, v[n].z);
}
glEnd();
glFlush();
SDL_GL_SwapBuffers();
glPopMatrix();
glPopAttrib();
}