00001
00002
00003
00004 #include "view.h"
00005 #include "common.h"
00006 #include "data.h"
00007 #include "model.h"
00008 #include "logic.h"
00009
00010 using namespace std;
00011
00012
00013 const double View::relative_x_margin = 1./20.;
00014 const double View::relative_y_margin = 1./20.;
00015
00016
00017 string View::str() const
00018 {
00019 char buffer[128];
00020 sprintf(buffer, "[%.12g:%.12g] [%.12g:%.12g]",
00021 hor.from, hor.to, ver.from, ver.to);
00022 return string(buffer);
00023 }
00024
00025 void View::change_view(const RealRange& hor_r, const RealRange& ver_r,
00026 const vector<int>& datasets)
00027 {
00028 assert(!datasets.empty());
00029
00030 hor = hor_r;
00031 ver = ver_r;
00032
00033
00034
00035
00036 DataAndModel const* first = F->get_dm(datasets[0]);
00037 vector<Model const*> models(1, first->model());
00038 vector<Data const*> datas(datasets.size());
00039 datas[0] = first->data();
00040 for (size_t i = 1; i < datasets.size(); ++i)
00041 datas[i] = F->get_dm(datasets[i])->data();
00042
00043 if (hor.from_inf() || hor.to_inf()) {
00044 double x_min=0, x_max=0;
00045 get_x_range(datas, x_min, x_max);
00046 if (x_min == x_max) {
00047 x_min -= 0.1;
00048 x_max += 0.1;
00049 }
00050 if (log_x_) {
00051 x_min = max(epsilon, x_min);
00052 x_max = max(epsilon, x_max);
00053 double margin = log(x_max / x_min) * relative_x_margin;
00054 if (hor.from_inf())
00055 hor.from = exp(log(x_min) - margin);
00056 if (hor.to_inf())
00057 hor.to = exp(log(x_max) + margin);
00058 }
00059 else {
00060 double margin = (x_max - x_min) * relative_x_margin;
00061 if (hor.from_inf())
00062 hor.from = x_min - margin;
00063 if (hor.to_inf())
00064 hor.to = x_max + margin;
00065 }
00066 }
00067
00068 if (ver.from_inf() || ver.to_inf()) {
00069 double y_min=0, y_max=0;
00070 get_y_range(datas, models, y_min, y_max);
00071 if (y_min == y_max) {
00072 y_min -= 0.1;
00073 y_max += 0.1;
00074 }
00075 if (log_y_) {
00076 y_min = max(epsilon, y_min);
00077 y_max = max(epsilon, y_max);
00078 double margin = log(y_max / y_min) * relative_y_margin;
00079 if (ver.from_inf())
00080 ver.from = exp(log(y_min) - margin);
00081 if (ver.to_inf())
00082 ver.to = exp(log(y_max) + margin);
00083 }
00084 else {
00085 double margin = (y_max - y_min) * relative_y_margin;
00086 if (ver.from_inf())
00087 ver.from = y_min - margin;
00088 if (ver.to_inf())
00089 ver.to = y_max + margin;
00090 }
00091 }
00092 }
00093
00094
00095 void View::get_x_range(vector<Data const*> datas, double &x_min, double &x_max)
00096 {
00097 if (datas.empty())
00098 throw ExecuteError("Can't find x-y axes ranges for plot");
00099 x_min = datas.front()->get_x_min();
00100 x_max = datas.front()->get_x_max();
00101 for (vector<Data const*>::const_iterator i = datas.begin() + 1;
00102 i != datas.end(); ++i) {
00103 x_min = min(x_min, (*i)->get_x_min());
00104 x_max = max(x_max, (*i)->get_x_max());
00105 }
00106 }
00107
00108
00109 void View::get_y_range(vector<Data const*> datas, vector<Model const*> models,
00110 double &y_min, double &y_max)
00111 {
00112 if (datas.empty())
00113 throw ExecuteError("Can't find x-y axes ranges for plot");
00114 y_min = y_max = (datas.front()->get_n() > 0 ? datas.front()->get_y(0) : 0);
00115 bool min_max_set = false;
00116 v_foreach (Data const*, i, datas) {
00117 vector<Point>::const_iterator f = (*i)->get_point_at(hor.from);
00118 vector<Point>::const_iterator l = (*i)->get_point_at(hor.to);
00119
00120 for (vector<Point>::const_iterator j = f; j < l; j++) {
00121 if (j->is_active && is_finite(j->y)) {
00122 min_max_set = true;
00123 if (j->y > y_max)
00124 y_max = j->y;
00125 if (j->y < y_min)
00126 y_min = j->y;
00127 }
00128 }
00129 }
00130
00131 if (!min_max_set || y_min == y_max) {
00132
00133 v_foreach (Data const*, i, datas) {
00134 vector<Point>::const_iterator f = (*i)->get_point_at(hor.from);
00135 vector<Point>::const_iterator l = (*i)->get_point_at(hor.to);
00136 for (vector<Point>::const_iterator j = f; j < l; j++) {
00137 if (!is_finite(j->y))
00138 continue;
00139 min_max_set = true;
00140 if (j->y > y_max)
00141 y_max = j->y;
00142 if (j->y < y_min)
00143 y_min = j->y;
00144 }
00145 }
00146 }
00147
00148 v_foreach (Model const*, i, models) {
00149 Model const* model = *i;
00150 if (model->get_ff().empty())
00151 continue;
00152
00153 double model_y_max = model->approx_max(hor.from, hor.to);
00154 if (model_y_max > y_max)
00155 y_max = model_y_max;
00156 if (model_y_max < y_min)
00157 y_min = model_y_max;
00158 }
00159
00160
00161 if (!log_y_ && y0_factor_ > 0) {
00162 double dy = y_max - y_min;
00163 if (y_min > 0 && y0_factor_ * dy > y_max)
00164 y_min = 0;
00165 else if (y_max < 0 && y0_factor_ * dy > fabs(y_min))
00166 y_max = 0;
00167 }
00168 }
00169