File: plot.h

package info (click to toggle)
fityk 1.3.2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,772 kB
  • sloc: cpp: 34,595; ansic: 4,676; python: 963; makefile: 384; sh: 119; xml: 91; java: 31; ruby: 27; perl: 25
file content (201 lines) | stat: -rw-r--r-- 6,332 bytes parent folder | download | duplicates (2)
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr
// Licence: GNU General Public License ver. 2+

#ifndef FITYK_WX_PLOT_H_
#define FITYK_WX_PLOT_H_

#include <limits.h>
#include <vector>
#include <wx/config.h>
#include "fityk/fityk.h" // Point
#include "fityk/common.h" // iround()
#include "uplot.h" // BufferedPanel
#include "cmn.h" // compatibility with wx2.8 (defined wxPenStyle, etc.)

// convention: lowercase coordinates of point are real values,
// and uppercase ones are coordinates of point on screen (integers).

// INT_MIN, given as coordinate, is invalid value, means "cancel drawing"

namespace fityk { class Model; class Data; struct Rect; }
using fityk::Point;
class wxPoint2DDouble;

inline int get_pixel_width(wxDC const& dc)
{
      int w;
      dc.GetClippingBox(NULL, NULL, &w, NULL);
      //if (w != 0) printf("Clipping On (width)\n");
      return w != 0 ? w : dc.GetSize().GetWidth();
}
inline int get_pixel_height(wxDC const& dc)
{
      int h;
      dc.GetClippingBox(NULL, NULL, NULL, &h);
      //if (h != 0) printf("Clipping On (height)\n");
      return h != 0 ? h : dc.GetSize().GetHeight();
}



/// convertion between pixels and logical values
class Scale
{
public:
    double scale, origin;
    bool logarithm, reversed;

    Scale() : scale(1.), origin(0.), logarithm(false), reversed(false) {}

    /// value -> pixel
    int px(double val) const { return iround(px_d(val)); }
    inline double px_d(double val) const;
    /// pixel -> value
    inline double val(int px) const;

    // Returns the same value as val(), but rounded in a smart way,
    // so when the number is formatted with "%.12g", it is not too long.
    double valr(int px) const;

    // set scale using minimum and maximum logical values and width/height
    // of the screen in pixels.
    // In case of y scale, where pixel=0 is at the top, m and M are switched
    void set(double m, double M, int pixels);

private:
    static int inf_px(double t) { return t > 0 ? SHRT_MAX : SHRT_MIN; }
};


double Scale::px_d(double val) const
{
    if (logarithm) {
        if (val <= 0)
            return inf_px(-scale);
        val = log(val);
    }
    double t = (val - origin) * scale;
    return fabs(t) < SHRT_MAX ? t : (double) inf_px(t);
}

double Scale::val(int px) const
{
    double a = px / scale + origin;
    return logarithm ? exp(a) : a;
}



class Overlay
{
public:
    enum Mode
    {
        kNone,
        kRect,
        kLinearDraft,
        kPeakDraft,
        kSigmoidDraft,
        kFunction,
        kCrossHair,
        kVLine,
        kHLine,
        kVRange,
        kHRange
    };
    Overlay(BufferedPanel *panel) : panel_(panel), mode_(kNone),
                                    color_(192,192,192) {}
    void start_mode(Mode m, int x1, int y1) { mode_=m; x1_=x2_=x1; y1_=y2_=y1; }
    void switch_mode(Mode m) { mode_=m; }
    void change_pos(int x2,int y2)
        { x2_=x2; y2_=y2; if (mode_!=kNone) draw_overlay(); }
    void draw_overlay();
    void draw_lines(int n, wxPoint points[]);
    Mode mode() const { return mode_; }
    void bg_color_updated(const wxColour& bg);

private:
    BufferedPanel *panel_;
    Mode mode_;
    wxColour color_;
    int x1_, x2_, y1_, y2_;
};



/// This class has no instances, MainPlot and AuxPlot are derived from it
/// It knows how to draw on wxDC. Note that wxDC:SetClippingRegion() should be
/// used together with wxDC::SetDeviceOrigin(). Clipping box is used only in
/// get_pixel_width() and get_pixel_height() functions.
/// When plotting a curve, values in each x from 0 to get_pixel_width() is
/// calculated.

class FPlot : public BufferedPanel
{
public:
    FPlot(wxWindow *parent);
    virtual ~FPlot();

    void set_font(wxDC &dc, wxFont const& font);
    void set_scale(int pixel_width, int pixel_height);
    int get_special_point_at_pointer(wxMouseEvent& event);
    Scale & get_x_scale() { return xs; }
    Scale & get_y_scale() { return ys; }
    virtual void save_settings(wxConfigBase *cf) const;
    virtual void read_settings(wxConfigBase *cf);
    void set_magnification(int m) { pen_width = m > 0 ? m : 1; }
    void draw_vertical_lines_on_overlay(int X1, int X2);
    virtual void set_bg_color(wxColour const& c);

protected:
    Scale xs, ys;
    Overlay overlay;

    // properties stored in config
    int pen_width;
    wxColour activeDataCol, inactiveDataCol, xAxisCol;
    wxFont ticsFont;
    int point_radius;
    bool line_between_points;
    bool draw_sigma;
    bool x_axis_visible, y_axis_visible, xtics_visible, ytics_visible,
         xminor_tics_visible, yminor_tics_visible;
    bool x_grid, y_grid;
    int x_max_tics, y_max_tics, x_tic_size, y_tic_size;

    int downX, downY;
    std::vector<wxPoint> special_points; //used to mark positions of peak tops
    wxWindow *esc_source_; // temporary source of OnKeyDown() events

    void draw_xtics (wxDC& dc, fityk::Rect const& v, bool set_pen=true);
    void draw_ytics (wxDC& dc, fityk::Rect const &v, bool set_pen=true);
    double get_max_abs_y(double (*compute_y)(std::vector<Point>::const_iterator,
                                             fityk::Model const*),
                         std::vector<Point>::const_iterator first,
                         std::vector<Point>::const_iterator last,
                         fityk::Model const* model);
    void draw_data (wxDC& dc,
                    double (*compute_y)(std::vector<Point>::const_iterator,
                                        fityk::Model const*),
                    fityk::Data const* data,
                    fityk::Model const* model,
                    wxColour const& color = wxNullColour,
                    wxColour const& inactive_color = wxNullColour,
                    int Y_offset = 0,
                    bool cumulative=false);

    // if connect is true: connect, otherwise disconnect;
    // connect to the currently focused window and handle wxEVT_KEY_DOWN 
    // event: if Esc is pressed call cancel_action().
    void connect_esc_to_cancel(bool connect);

    virtual void cancel_action() {}
    // handler used by connect_esc_to_cancel()
    void OnKeyDown(wxKeyEvent& event);
private:
    void draw_data_by_activity(wxDC& dc, wxPoint2DDouble *pp,
                               const std::vector<bool>& aa, bool state);
};

#endif