braille_plot.h 4.08 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#ifndef _SPELL_BRAILLE_PLOT_H_
#define _SPELL_BRAILLE_PLOT_H_

#include <iostream>
#include "eigen.h"


struct braille_plot {
    int m_width;
    int m_height;
    typedef Eigen::Matrix<unsigned long, Eigen::Dynamic, Eigen::Dynamic> plot_data_type;
    plot_data_type m_data;
    double m_xmin;
    double m_xmax;
    double m_ymin;
    double m_ymax;
    double m_xrange_inv;
    double m_yrange_inv;

    braille_plot(int w, int h, double min_x, double max_x, double min_y, double max_y)
        : m_width((w << 1)), m_height((h << 2)), m_data(plot_data_type::Constant(h + 1, w + 1, 0x0080A0E2)),
          m_xmin(min_x), m_xmax(max_x), m_ymin(min_y), m_ymax(max_y),
          m_xrange_inv(1. / (m_xmax - m_xmin)),
          m_yrange_inv(1. / (m_ymax - m_ymin))
    {}

    braille_plot&
        put_pixel(double x, double y)
        {
            int ix = x2plot(x);
            int iy = y2plot(y);
            unsigned long bit = xy2bit(ix, iy);
            int r = y2data(iy);
            int c = x2data(ix);
            if (r >= 0 && r < m_data.rows() && c >= 0 && c < m_data.cols()) {
                m_data(r, c) |= bit;
                /*std::cout << "put_pixel(" << std::dec << x << ", " << y << ") ix=" << ix << " iy=" << iy << " bit=" << std::hex << bit << std::dec << " r=" << r << " c=" << c << " data=" << std::hex << m_data(r, c) << std::endl;*/
            }
            return *this;
        }

    braille_plot&
        clear_pixel(double x, double y)
        {
            int ix = x2plot(x);
            int iy = y2plot(y);
            unsigned char bit = xy2bit(ix, iy);
            int r = y2data(iy);
            int c = x2data(ix);
            if (r >= 0 && r < m_data.rows() && c >= 0 && c < m_data.cols()) {
                m_data(r, c) &= ~bit;
            }
            return *this;
        }

    bool
        get_pixel(double x, double y) const
        {
            int ix = x2plot(x);
            int iy = y2plot(y);
            unsigned char bit = xy2bit(ix, iy);
            int r = y2data(iy);
            int c = x2data(ix);
            if (r >= 0 && r < m_data.rows() && c >= 0 && c < m_data.cols()) {
                return !!(m_data(r, c) & bit);
            }
            return false;
        }

    template <typename FUN>
    braille_plot&
        plot(FUN fun, double step)
        {
            for (double x = m_xmin; x < m_xmax; x += step) {
                put_pixel(x, fun(x));
            }
            return *this;
        }

    friend
        std::ostream& operator << (std::ostream& os, const braille_plot& plot)
        {
            /*static Eigen::IOFormat fmt(Eigen::StreamPrecision, Eigen::DontAlignCols,*/
                                       /*"", "\n",*/
                                       /*"", "",*/
                                       /*"", "");*/
            /*return os << plot.m_data.format(fmt);*/
            /*static Eigen::IOFormat fmt(Eigen::StreamPrecision, Eigen::DontAlignCols,*/
                                       /*"\x28", "\n",*/
                                       /*"\x28", "",*/
                                       /*"", "");*/
            /*return os << plot.m_data.format(fmt);*/
            
            for (int r = 0; r < plot.m_data.rows(); ++r) {
                for (int c = 0; c < plot.m_data.cols(); ++c) {
                    os.write((char*) &plot.m_data(r, c), 3);
                }
                os << std::endl;
            }
            return os;
        }

private:
    int x2data(int x) const { return x >> 1; }
    int y2data(int y) const { return y >> 2; }

    unsigned long xy2bit(int x, int y) const
    {
        static unsigned int bitval[8] = {
            0x010000, 0x080000,
            0x020000, 0x100000,
            0x040000, 0x200000,
            0x000100, 0x000200
        };

        return bitval[ ((y & 0x3) << 1) | (x & 1) ];
    }

    int x2plot(double x) const
    {
        double rel_x = (x - m_xmin) * m_xrange_inv;
        return (int) round(m_width * rel_x);
    }

    int y2plot(double y) const
    {
        double rel_y = 1 - (y - m_ymin) * m_yrange_inv;
        return (int) round(m_height * rel_y);
    }
};



#endif