/* 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(); }