Stefan Schuermans commited on 2017-06-10 23:09:20
              Showing 15 changed files, with 474 additions and 27 deletions.
            
| ... | ... | @@ -0,0 +1,76 @@ | 
| 1 | +/* | |
| 2 | + * EtherPix simulator | |
| 3 | + * | |
| 4 | + * Copyright 2017 Stefan Schuermans <stefan schuermans info> | |
| 5 | + * | |
| 6 | + * This program is free software: you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation, version 3 of the License. | |
| 9 | + * | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public License | |
| 17 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#include "bbox.h" | |
| 21 | + | |
| 22 | +/// constructor | |
| 23 | +BBox::BBox(): | |
| 24 | + m_init(false), | |
| 25 | + m_x_min(0.0), | |
| 26 | + m_x_max(0.0), | |
| 27 | + m_y_min(0.0), | |
| 28 | + m_y_max(0.0) | |
| 29 | +{ | |
| 30 | +} | |
| 31 | + | |
| 32 | +/// reset bounding box (de-initialize) | |
| 33 | +void BBox::reset() | |
| 34 | +{ | |
| 35 | + m_init = false; | |
| 36 | + m_x_min = 0.0; | |
| 37 | + m_x_max = 0.0; | |
| 38 | + m_y_min = 0.0; | |
| 39 | + m_y_max = 0.0; | |
| 40 | +} | |
| 41 | + | |
| 42 | +// add a point to the bounding box | |
| 43 | +void BBox::add(double x, double y) | |
| 44 | +{ | |
| 45 | +  if (m_init) { | |
| 46 | + if (x < m_x_min) m_x_min = x; | |
| 47 | + if (x > m_x_max) m_x_max = x; | |
| 48 | + if (y < m_y_min) m_y_min = y; | |
| 49 | + if (y > m_y_max) m_y_max = y; | |
| 50 | +  } else { | |
| 51 | + m_init = true; | |
| 52 | + m_x_min = x; | |
| 53 | + m_x_max = x; | |
| 54 | + m_y_min = y; | |
| 55 | + m_y_max = y; | |
| 56 | + } | |
| 57 | +} | |
| 58 | + | |
| 59 | +/** | |
| 60 | + * @brief get coordinates | |
| 61 | + * @return whether coordinates were there | |
| 62 | + */ | |
| 63 | +bool BBox::get(double &x_min, double &x_max, | |
| 64 | + double &y_min, double &y_max) const | |
| 65 | +{ | |
| 66 | +  if (m_init) { | |
| 67 | + x_min = m_x_min; | |
| 68 | + x_max = m_x_max; | |
| 69 | + y_min = m_y_min; | |
| 70 | + y_max = m_y_max; | |
| 71 | + return true; | |
| 72 | +  } else { | |
| 73 | + return false; | |
| 74 | + } | |
| 75 | +} | |
| 76 | + | 
| ... | ... | @@ -0,0 +1,52 @@ | 
| 1 | +/* | |
| 2 | + * EtherPix simulator | |
| 3 | + * | |
| 4 | + * Copyright 2017 Stefan Schuermans <stefan schuermans info> | |
| 5 | + * | |
| 6 | + * This program is free software: you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation, version 3 of the License. | |
| 9 | + * | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public License | |
| 17 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#ifndef BBOX_H | |
| 21 | +#define BBOX_H | |
| 22 | + | |
| 23 | +/// bounding box | |
| 24 | +class BBox | |
| 25 | +{ | |
| 26 | +public: | |
| 27 | + /// constructor | |
| 28 | + BBox(); | |
| 29 | + | |
| 30 | + /// reset bounding box (de-initialize) | |
| 31 | + void reset(); | |
| 32 | + | |
| 33 | + /// add a point to the bounding box | |
| 34 | + void add(double x, double y); | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * @brief get coordinates | |
| 38 | + * @return whether coordinates were there | |
| 39 | + */ | |
| 40 | + bool get(double &x_min, double &x_max, | |
| 41 | + double &y_min, double &y_max) const; | |
| 42 | + | |
| 43 | +protected: | |
| 44 | + bool m_init; ///< initialization flag, false means no coordinates yet | |
| 45 | + double m_x_min; ///< minimum x coordinate | |
| 46 | + double m_x_max; ///< maximum y coordinate | |
| 47 | + double m_y_min; ///< minimum x coordinate | |
| 48 | + double m_y_max; ///< maximum y coordinate | |
| 49 | +}; | |
| 50 | + | |
| 51 | +#endif // #ifndef BBOX_H | |
| 52 | + | 
| ... | ... | @@ -31,6 +31,7 @@ | 
| 31 | 31 | #include <string> | 
| 32 | 32 | #include <sys/socket.h> | 
| 33 | 33 |  | 
| 34 | +#include "bbox.h" | |
| 34 | 35 | #include "config.h" | 
| 35 | 36 | #include "distri.h" | 
| 36 | 37 | #include "mapping.h" | 
| ... | ... | @@ -40,11 +41,28 @@ | 
| 40 | 41 | * @brief constructor | 
| 41 | 42 | * @param[in] configFile name of config file | 
| 42 | 43 | */ | 
| 43 | -Config::Config(std::string const &configFile) | |
| 44 | +Config::Config(std::string const &configFile): | |
| 45 | + m_distriMap(), | |
| 46 | + m_bb() | |
| 44 | 47 |  { | 
| 45 | 48 | readFile(configFile); | 
| 46 | 49 | } | 
| 47 | 50 |  | 
| 51 | +/** | |
| 52 | + * @brief draw pixels of all distributors | |
| 53 | + * @param[in] cairo cairo context for drawing | |
| 54 | + * @param[in] tf coordinate transformation | |
| 55 | + */ | |
| 56 | +void Config::draw(Cairo::RefPtr<Cairo::Context> &cairo, | |
| 57 | + Transform const &tf) const | |
| 58 | +{ | |
| 59 | + DistriMap::const_iterator dist; | |
| 60 | +  for (dist = m_distriMap.begin(); dist != m_distriMap.end(); ++dist) { | |
| 61 | + Distri const &distri = dist->second; | |
| 62 | + distri.draw(cairo, tf); | |
| 63 | + } | |
| 64 | +} | |
| 65 | + | |
| 48 | 66 | /** | 
| 49 | 67 | * @brief remove whitespace at beging and end of string | 
| 50 | 68 | * @param[in,out] str string to process | 
| ... | ... | @@ -343,6 +361,9 @@ void Config::readFile(std::string const &configFile) | 
| 343 | 361 |  | 
| 344 | 362 | // close file | 
| 345 | 363 | cf.close(); | 
| 364 | + | |
| 365 | + // update internal data | |
| 366 | + update(); | |
| 346 | 367 | } | 
| 347 | 368 |  | 
| 348 | 369 | /** | 
| ... | ... | @@ -727,3 +748,15 @@ Distri & Config::getDistri(unsigned long distno) | 
| 727 | 748 | return distri->second; | 
| 728 | 749 | } | 
| 729 | 750 |  | 
| 751 | +/// update internal data | |
| 752 | +void Config::update() | |
| 753 | +{ | |
| 754 | + // re-compute bounding box of all pixels | |
| 755 | + m_bb.reset(); | |
| 756 | + DistriMap::const_iterator dist; | |
| 757 | +  for (dist = m_distriMap.begin(); dist != m_distriMap.end(); ++dist) { | |
| 758 | + Distri const &distri = dist->second; | |
| 759 | + distri.updateBBox(m_bb); | |
| 760 | + } | |
| 761 | +} | |
| 762 | + | 
| ... | ... | @@ -21,11 +21,14 @@ | 
| 21 | 21 | #define CONFIG_H | 
| 22 | 22 |  | 
| 23 | 23 | #include <arpa/inet.h> | 
| 24 | +#include <gtkmm.h> | |
| 24 | 25 | #include <map> | 
| 25 | 26 | #include <string> | 
| 26 | 27 | #include <vector> | 
| 27 | 28 |  | 
| 29 | +#include "bbox.h" | |
| 28 | 30 | #include "distri.h" | 
| 31 | +#include "transform.h" | |
| 29 | 32 |  | 
| 30 | 33 | /// config file | 
| 31 | 34 | class Config | 
| ... | ... | @@ -37,6 +40,16 @@ public: | 
| 37 | 40 | */ | 
| 38 | 41 | Config(std::string const &configFile); | 
| 39 | 42 |  | 
| 43 | + /// get bounding box | |
| 44 | +  BBox const &getBBox() const { return m_bb; } | |
| 45 | + | |
| 46 | + /** | |
| 47 | + * @brief draw pixels of all distributors | |
| 48 | + * @param[in] cairo cairo context for drawing | |
| 49 | + * @param[in] tf coordinate transformation | |
| 50 | + */ | |
| 51 | + void draw(Cairo::RefPtr<Cairo::Context> &cairo, Transform const &tf) const; | |
| 52 | + | |
| 40 | 53 | protected: | 
| 41 | 54 | /// distributor map: distributor number -> distributor object | 
| 42 | 55 | typedef std::map<unsigned long, Distri> DistriMap; | 
| ... | ... | @@ -182,9 +195,14 @@ protected: | 
| 182 | 195 | */ | 
| 183 | 196 | Distri & getDistri(unsigned long distno); | 
| 184 | 197 |  | 
| 198 | + /// update internal data | |
| 199 | + void update(); | |
| 200 | + | |
| 185 | 201 | protected: | 
| 186 | 202 | /// distributors | 
| 187 | 203 | DistriMap m_distriMap; | 
| 204 | + /// bounding box of all pixels | |
| 205 | + BBox m_bb; | |
| 188 | 206 | }; | 
| 189 | 207 |  | 
| 190 | 208 | #endif // #ifndef CONFIG_H | 
| ... | ... | @@ -18,14 +18,17 @@ | 
| 18 | 18 | */ | 
| 19 | 19 |  | 
| 20 | 20 | #include <arpa/inet.h> | 
| 21 | +#include <gtkmm.h> | |
| 21 | 22 | #include <map> | 
| 22 | 23 | #include <sstream> | 
| 23 | 24 | #include <stdexcept> | 
| 24 | 25 | #include <vector> | 
| 25 | 26 |  | 
| 27 | +#include "bbox.h" | |
| 26 | 28 | #include "distri.h" | 
| 27 | 29 | #include "mapping.h" | 
| 28 | 30 | #include "pixel.h" | 
| 31 | +#include "transform.h" | |
| 29 | 32 |  | 
| 30 | 33 | /// constructor | 
| 31 | 34 | Distri::Distri(): | 
| ... | ... | @@ -141,3 +144,39 @@ void Distri::addPixel(unsigned long outno, Pixel const &pixel) | 
| 141 | 144 | output.m_pixels.push_back(pixel); | 
| 142 | 145 | } | 
| 143 | 146 |  | 
| 147 | +/** | |
| 148 | + * @brief add all pixels of this distributor to the bounding box | |
| 149 | + * @param[in,out] bb bounding box | |
| 150 | + */ | |
| 151 | +void Distri::updateBBox(BBox &bb) const | |
| 152 | +{ | |
| 153 | + OutputMap::const_iterator out; | |
| 154 | +  for (out = m_outputMap.begin(); out != m_outputMap.end(); ++out) { | |
| 155 | + Output const &output = out->second; | |
| 156 | + std::vector<Pixel>::const_iterator pix; | |
| 157 | +    for (pix = output.m_pixels.begin(); pix != output.m_pixels.end(); ++pix) { | |
| 158 | + Pixel const &pixel = *pix; | |
| 159 | + pixel.updateBBox(bb); | |
| 160 | + } | |
| 161 | + } | |
| 162 | +} | |
| 163 | + | |
| 164 | +/** | |
| 165 | + * @brief draw pixels of this distributor | |
| 166 | + * @param[in] cairo cairo context for drawing | |
| 167 | + * @param[in] tf coordinate transformation | |
| 168 | + */ | |
| 169 | +void Distri::draw(Cairo::RefPtr<Cairo::Context> &cairo, | |
| 170 | + Transform const &tf) const | |
| 171 | +{ | |
| 172 | + OutputMap::const_iterator out; | |
| 173 | +  for (out = m_outputMap.begin(); out != m_outputMap.end(); ++out) { | |
| 174 | + Output const &output = out->second; | |
| 175 | + std::vector<Pixel>::const_iterator pix; | |
| 176 | +    for (pix = output.m_pixels.begin(); pix != output.m_pixels.end(); ++pix) { | |
| 177 | + Pixel const &pixel = *pix; | |
| 178 | + pixel.draw(cairo, tf); | |
| 179 | + } | |
| 180 | + } | |
| 181 | +} | |
| 182 | + | 
| ... | ... | @@ -21,11 +21,14 @@ | 
| 21 | 21 | #define DISTRI_H | 
| 22 | 22 |  | 
| 23 | 23 | #include <arpa/inet.h> | 
| 24 | +#include <gtkmm.h> | |
| 24 | 25 | #include <map> | 
| 25 | 26 | #include <vector> | 
| 26 | 27 |  | 
| 28 | +#include "bbox.h" | |
| 27 | 29 | #include "mapping.h" | 
| 28 | 30 | #include "pixel.h" | 
| 31 | +#include "transform.h" | |
| 29 | 32 |  | 
| 30 | 33 | /// distributor | 
| 31 | 34 | class Distri | 
| ... | ... | @@ -88,6 +91,19 @@ public: | 
| 88 | 91 | */ | 
| 89 | 92 | void addPixel(unsigned long outno, Pixel const &pixel); | 
| 90 | 93 |  | 
| 94 | + /** | |
| 95 | + * @brief add all pixels of this distributor to the bounding box | |
| 96 | + * @param[in,out] bb bounding box | |
| 97 | + */ | |
| 98 | + void updateBBox(BBox &bb) const; | |
| 99 | + | |
| 100 | + /** | |
| 101 | + * @brief draw pixels of this distributor | |
| 102 | + * @param[in] cairo cairo context for drawing | |
| 103 | + * @param[in] tf coordinate transformation | |
| 104 | + */ | |
| 105 | + void draw(Cairo::RefPtr<Cairo::Context> &cairo, Transform const &tf) const; | |
| 106 | + | |
| 91 | 107 | protected: | 
| 92 | 108 | /// output data | 
| 93 | 109 |    struct Output { | 
| ... | ... | @@ -19,7 +19,9 @@ | 
| 19 | 19 |  | 
| 20 | 20 | #include <gtkmm.h> | 
| 21 | 21 |  | 
| 22 | +#include "config.h" | |
| 22 | 23 | #include "draw.h" | 
| 24 | +#include "transform.h" | |
| 23 | 25 |  | 
| 24 | 26 | /** | 
| 25 | 27 | * @brief constructor | 
| ... | ... | @@ -29,17 +31,9 @@ | 
| 29 | 31 | Draw::Draw(BaseObjectType *cobject, | 
| 30 | 32 | const Glib::RefPtr<Gtk::Builder> &builder): | 
| 31 | 33 | Gtk::DrawingArea(cobject), | 
| 32 | - m_builder(builder) | |
| 34 | + m_builder(builder), | |
| 35 | + m_config(NULL) | |
| 33 | 36 |  { | 
| 34 | - /* | |
| 35 | - TODO | |
| 36 | - // connect callbacks (seems to be needed for gtkmm-2.4 < V2.16) | |
| 37 | - signal_configure_event().connect( | |
| 38 | - sigc::mem_fun(*this, &Draw::on_configure_event)); | |
| 39 | - signal_expose_event().connect( | |
| 40 | - sigc::mem_fun(*this, &Draw::on_expose_event)); | |
| 41 | - */ | |
| 42 | - | |
| 43 | 37 | // initialize image | 
| 44 | 38 | updateImage(); | 
| 45 | 39 | queue_draw(); | 
| ... | ... | @@ -50,6 +44,15 @@ Draw::~Draw() | 
| 50 | 44 |  { | 
| 51 | 45 | } | 
| 52 | 46 |  | 
| 47 | +/// set configuration object | |
| 48 | +void Draw::setConfig(Config const&config) | |
| 49 | +{ | |
| 50 | + m_config = &config; | |
| 51 | + | |
| 52 | + // re-initialize image | |
| 53 | + updateImage(); | |
| 54 | + queue_draw(); | |
| 55 | +} | |
| 53 | 56 |  | 
| 54 | 57 | /** | 
| 55 | 58 | * @brief widget is (re)configured | 
| ... | ... | @@ -101,19 +104,13 @@ void Draw::updateImage() | 
| 101 | 104 | cairo->rectangle(0, 0, width, height); | 
| 102 | 105 | cairo->fill(); | 
| 103 | 106 |  | 
| 104 | - // TODO | |
| 105 | - // draw circles | |
| 106 | - cairo->set_source_rgb(1.0, 0.0, 0.0); | |
| 107 | - cairo->arc(0.5 * width, 0.5 * height, 0.03 * (width + height), | |
| 108 | - 0.0, 2.0 * M_PI); | |
| 109 | - cairo->fill(); | |
| 110 | - cairo->set_source_rgb(0.0, 1.0, 0.0); | |
| 111 | - cairo->arc(0.7 * width, 0.3 * height, 0.03 * (width + height), | |
| 112 | - 0.0, 2.0 * M_PI); | |
| 113 | - cairo->fill(); | |
| 114 | - cairo->set_source_rgb(0.0, 0.0, 1.0); | |
| 115 | - cairo->arc(0.7 * width, 0.7 * height, 0.03 * (width + height), | |
| 116 | - 0.0, 2.0 * M_PI); | |
| 117 | - cairo->fill(); | |
| 107 | + // compute coordinate transformation | |
| 108 | + if (! m_config) | |
| 109 | + return; | |
| 110 | + Transform tf(m_config->getBBox(), width, height); | |
| 111 | + | |
| 112 | + // draw pixels of all distributors | |
| 113 | + cairo->set_source_rgb(1.0, 0.0, 0.0); // FIXME | |
| 114 | + m_config->draw(cairo, tf); | |
| 118 | 115 | } | 
| 119 | 116 |  | 
| ... | ... | @@ -22,6 +22,8 @@ | 
| 22 | 22 |  | 
| 23 | 23 | #include <gtkmm.h> | 
| 24 | 24 |  | 
| 25 | +#include "config.h" | |
| 26 | + | |
| 25 | 27 | /// drawing area | 
| 26 | 28 | class Draw: public Gtk::DrawingArea | 
| 27 | 29 |  { | 
| ... | ... | @@ -37,6 +39,8 @@ public: | 
| 37 | 39 | /// virtual destructor | 
| 38 | 40 | virtual ~Draw(); | 
| 39 | 41 |  | 
| 42 | + /// set configuration object | |
| 43 | + void setConfig(Config const&config); | |
| 40 | 44 |  | 
| 41 | 45 | protected: | 
| 42 | 46 | /** | 
| ... | ... | @@ -62,6 +66,9 @@ protected: | 
| 62 | 66 |  | 
| 63 | 67 | /// cairo surface with current simulator image | 
| 64 | 68 | Cairo::RefPtr<Cairo::ImageSurface> m_image; | 
| 69 | + | |
| 70 | + /// configuration object | |
| 71 | + Config const *m_config; | |
| 65 | 72 | }; | 
| 66 | 73 |  | 
| 67 | 74 | #endif // #ifndef DRAW_H | 
| ... | ... | @@ -49,6 +49,7 @@ int main(int argc, char *argv[]) | 
| 49 | 49 | // connect main window to its class | 
| 50 | 50 | MainWindow *mainWindow; | 
| 51 | 51 |      builder->get_widget_derived("MainWindow", mainWindow); | 
| 52 | + mainWindow->setConfig(config); | |
| 52 | 53 |  | 
| 53 | 54 | // append config file name to window title | 
| 54 | 55 | mainWindow->set_title(mainWindow->get_title() + " - " + configFile); | 
| ... | ... | @@ -18,8 +18,9 @@ | 
| 18 | 18 | */ | 
| 19 | 19 |  | 
| 20 | 20 | #include <gtkmm.h> | 
| 21 | -//#include <libglademm/xml.h> | |
| 22 | 21 |  | 
| 22 | +#include "config.h" | |
| 23 | +#include "draw.h" | |
| 23 | 24 | #include "main_window.h" | 
| 24 | 25 |  | 
| 25 | 26 | /** | 
| ... | ... | @@ -30,7 +31,8 @@ | 
| 30 | 31 | MainWindow::MainWindow(BaseObjectType *cobject, | 
| 31 | 32 | const Glib::RefPtr<Gtk::Builder> &builder): | 
| 32 | 33 | Gtk::Window(cobject), | 
| 33 | - m_builder(builder) | |
| 34 | + m_builder(builder), | |
| 35 | + m_config(NULL) | |
| 34 | 36 |  { | 
| 35 | 37 | // get widgets | 
| 36 | 38 |    builder->get_widget_derived("Draw", m_draw); | 
| ... | ... | @@ -45,6 +47,13 @@ MainWindow::~MainWindow() | 
| 45 | 47 |  { | 
| 46 | 48 | } | 
| 47 | 49 |  | 
| 50 | +/// set configuration object | |
| 51 | +void MainWindow::setConfig(Config const &config) | |
| 52 | +{ | |
| 53 | + m_config = &config; | |
| 54 | + m_draw->setConfig(config); | |
| 55 | +} | |
| 56 | + | |
| 48 | 57 | /// window is being hidden | 
| 49 | 58 | void MainWindow::on_hide() | 
| 50 | 59 |  { | 
| ... | ... | @@ -22,6 +22,7 @@ | 
| 22 | 22 |  | 
| 23 | 23 | #include <gtkmm.h> | 
| 24 | 24 |  | 
| 25 | +#include "config.h" | |
| 25 | 26 | #include "draw.h" | 
| 26 | 27 |  | 
| 27 | 28 | /// main window of StateTracker GUI | 
| ... | ... | @@ -39,6 +40,9 @@ public: | 
| 39 | 40 | /// virtual destructor | 
| 40 | 41 | virtual ~MainWindow(); | 
| 41 | 42 |  | 
| 43 | + /// set configuration object | |
| 44 | + void setConfig(Config const& config); | |
| 45 | + | |
| 42 | 46 | protected: | 
| 43 | 47 | /// window is being hidden | 
| 44 | 48 | void on_hide(); | 
| ... | ... | @@ -54,6 +58,9 @@ protected: | 
| 54 | 58 | Draw *m_draw; | 
| 55 | 59 | /// status bar | 
| 56 | 60 | Gtk::Statusbar *m_status; | 
| 61 | + | |
| 62 | + /// configuration object | |
| 63 | + Config const *m_config; | |
| 57 | 64 | }; | 
| 58 | 65 |  | 
| 59 | 66 | #endif // #ifndef MAIN_WINDOW_H | 
| ... | ... | @@ -17,7 +17,11 @@ | 
| 17 | 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 
| 18 | 18 | */ | 
| 19 | 19 |  | 
| 20 | +#include <gtkmm.h> | |
| 21 | + | |
| 22 | +#include "bbox.h" | |
| 20 | 23 | #include "pixel.h" | 
| 24 | +#include "transform.h" | |
| 21 | 25 |  | 
| 22 | 26 | /// default constructor | 
| 23 | 27 | Pixel::Pixel(): | 
| ... | ... | @@ -35,3 +39,29 @@ Pixel::Pixel(double x, double y, double r): | 
| 35 | 39 |  { | 
| 36 | 40 | } | 
| 37 | 41 |  | 
| 42 | +/** | |
| 43 | + * @brief add pixel to the bounding box | |
| 44 | + * @param[in,out] bb bounding box | |
| 45 | + */ | |
| 46 | +void Pixel::updateBBox(BBox &bb) const | |
| 47 | +{ | |
| 48 | + // add pixel plus some border to bounding box | |
| 49 | + bb.add(m_x - 2 * m_r, m_y - 2 * m_r); | |
| 50 | + bb.add(m_x + 2 * m_r, m_y + 2 * m_r); | |
| 51 | +} | |
| 52 | + | |
| 53 | +/** | |
| 54 | + * @brief draw pixel | |
| 55 | + * @param[in] cairo cairo context for drawing | |
| 56 | + * @param[in] tf coordinate transformation | |
| 57 | + */ | |
| 58 | +void Pixel::draw(Cairo::RefPtr<Cairo::Context> &cairo, | |
| 59 | + Transform const &tf) const | |
| 60 | +{ | |
| 61 | + double x, y, r; | |
| 62 | + tf.apply(m_x, m_y, x, y); | |
| 63 | + tf.applyZoom(m_r, r); | |
| 64 | + cairo->arc(x, y, r, 0.0, 2.0 * M_PI); | |
| 65 | + cairo->fill(); | |
| 66 | +} | |
| 67 | + | 
| ... | ... | @@ -20,6 +20,11 @@ | 
| 20 | 20 | #ifndef PIXEL_H | 
| 21 | 21 | #define PIXEL_H | 
| 22 | 22 |  | 
| 23 | +#include <gtkmm.h> | |
| 24 | + | |
| 25 | +#include "bbox.h" | |
| 26 | +#include "transform.h" | |
| 27 | + | |
| 23 | 28 | /// a simulated pixel | 
| 24 | 29 | class Pixel | 
| 25 | 30 |  { | 
| ... | ... | @@ -30,6 +35,19 @@ public: | 
| 30 | 35 | /// constructor based on coordinates and radius | 
| 31 | 36 | Pixel(double x, double y, double r); | 
| 32 | 37 |  | 
| 38 | + /** | |
| 39 | + * @brief add pixel to the bounding box | |
| 40 | + * @param[in,out] bb bounding box | |
| 41 | + */ | |
| 42 | + void updateBBox(BBox &bb) const; | |
| 43 | + | |
| 44 | + /** | |
| 45 | + * @brief draw pixel | |
| 46 | + * @param[in] cairo cairo context for drawing | |
| 47 | + * @param[in] tf coordinate transformation | |
| 48 | + */ | |
| 49 | + void draw(Cairo::RefPtr<Cairo::Context> &cairo, Transform const &tf) const; | |
| 50 | + | |
| 33 | 51 | protected: | 
| 34 | 52 | /// parameters of pixel | 
| 35 | 53 |     //@{ | 
| ... | ... | @@ -0,0 +1,80 @@ | 
| 1 | +/* | |
| 2 | + * EtherPix simulator | |
| 3 | + * | |
| 4 | + * Copyright 2017 Stefan Schuermans <stefan schuermans info> | |
| 5 | + * | |
| 6 | + * This program is free software: you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation, version 3 of the License. | |
| 9 | + * | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public License | |
| 17 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#include "bbox.h" | |
| 21 | +#include "transform.h" | |
| 22 | + | |
| 23 | +/** | |
| 24 | + * @brief constructor | |
| 25 | + * @param[in] bb boundig box of input coordinates | |
| 26 | + * @param[in] width width of output coordinate speace (left to right) | |
| 27 | + * @param[in] height height of output coordinate space (top to bottom) | |
| 28 | + */ | |
| 29 | +Transform::Transform(BBox const &bb, double width, double height): | |
| 30 | + m_init(false), | |
| 31 | + m_zoom(1.0), | |
| 32 | + m_shift_x(0.0), | |
| 33 | + m_shift_y(0.0) | |
| 34 | +{ | |
| 35 | + double bb_x_min, bb_x_max, bb_y_min, bb_y_max; | |
| 36 | + if (! bb.get(bb_x_min, bb_x_max, bb_y_min, bb_y_max)) | |
| 37 | + return; | |
| 38 | + | |
| 39 | + double delta_x = bb_x_max - bb_x_min; | |
| 40 | + double delta_y = bb_y_max - bb_y_min; | |
| 41 | + if (delta_x <= 0.0 || delta_y <= 0.0) | |
| 42 | + return; | |
| 43 | + | |
| 44 | + // compute zoom factor (keep aspect ration, fit into window) | |
| 45 | + double zoom_x = (double)width / delta_x; | |
| 46 | + double zoom_y = (double)height / delta_y; | |
| 47 | + m_zoom = zoom_x < zoom_y ? zoom_x : zoom_y; | |
| 48 | + | |
| 49 | + // compute shift (center of pixels should be center of window) | |
| 50 | + m_shift_x = 0.5 * (double)width - 0.5 * (bb_x_min + bb_x_max) * m_zoom; | |
| 51 | + m_shift_y = 0.5 * (double)height - 0.5 * (bb_y_min + bb_y_max) * -m_zoom; | |
| 52 | + | |
| 53 | + // initialized | |
| 54 | + m_init = true; | |
| 55 | +}; | |
| 56 | + | |
| 57 | +/** | |
| 58 | + * @brief apply transformation | |
| 59 | + * @param[in] in_x input x coordinate | |
| 60 | + * @param[in] in_y input y coordinate | |
| 61 | + * @param[out] out_x output x coordinate | |
| 62 | + * @param[out] out_y output y coordinate | |
| 63 | + */ | |
| 64 | +void Transform::apply(double in_x, double in_y, | |
| 65 | + double &out_x, double &out_y) const | |
| 66 | +{ | |
| 67 | + out_x = in_x * m_zoom + m_shift_x; | |
| 68 | + out_y = in_y * -m_zoom + m_shift_y; | |
| 69 | +} | |
| 70 | + | |
| 71 | +/** | |
| 72 | + * @brief apply zoom | |
| 73 | + * @param[in] in_r input radius | |
| 74 | + * @param[out] out_r output radius | |
| 75 | + */ | |
| 76 | +void Transform::applyZoom(double in_r, double &out_r) const | |
| 77 | +{ | |
| 78 | + out_r = in_r * m_zoom; | |
| 79 | +} | |
| 80 | + | 
| ... | ... | @@ -0,0 +1,64 @@ | 
| 1 | +/* | |
| 2 | + * EtherPix simulator | |
| 3 | + * | |
| 4 | + * Copyright 2017 Stefan Schuermans <stefan schuermans info> | |
| 5 | + * | |
| 6 | + * This program is free software: you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation, version 3 of the License. | |
| 9 | + * | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public License | |
| 17 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#ifndef TRANSFORM_H | |
| 21 | +#define TRANSFORM_H | |
| 22 | + | |
| 23 | +#include "bbox.h" | |
| 24 | + | |
| 25 | +/// coordinate transformation | |
| 26 | +class Transform | |
| 27 | +{ | |
| 28 | +public: | |
| 29 | + /** | |
| 30 | + * @brief constructor | |
| 31 | + * @param[in] bb boundig box of input coordinates | |
| 32 | + * @param[in] width width of output coordinate speace (left to right) | |
| 33 | + * @param[in] height height of output coordinate space (top to bottom) | |
| 34 | + */ | |
| 35 | + Transform(BBox const &bb, double width, double height); | |
| 36 | + | |
| 37 | + /// check if initialized | |
| 38 | +  bool checkInit() const { return m_init; } | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * @brief apply transformation | |
| 42 | + * @param[in] in_x input x coordinate | |
| 43 | + * @param[in] in_y input y coordinate | |
| 44 | + * @param[out] out_x output x coordinate | |
| 45 | + * @param[out] out_y output y coordinate | |
| 46 | + */ | |
| 47 | + void apply(double in_x, double in_y, double &out_x, double &out_y) const; | |
| 48 | + | |
| 49 | + /** | |
| 50 | + * @brief apply zoom | |
| 51 | + * @param[in] in_r input radius | |
| 52 | + * @param[out] out_r output radius | |
| 53 | + */ | |
| 54 | + void applyZoom(double in_r, double &out_r) const; | |
| 55 | + | |
| 56 | +protected: | |
| 57 | + bool m_init; ///< initialization flag, false means no transformation data | |
| 58 | + double m_zoom; ///< zoom factor (use negative for y direction) | |
| 59 | + double m_shift_x; ///< shift in x direction | |
| 60 | + double m_shift_y; ///< shift in y direction | |
| 61 | +}; | |
| 62 | + | |
| 63 | +#endif // #ifndef TRANSFORM_H | |
| 64 | + | |
| 0 | 65 |