Subversion Repositories DIN Is Noise

Rev

Rev 1485 | Rev 1582 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
* countries.cc
* DIN Is Noise is copyright (c) 2006-2020 Jagannathan Sampath
* For more information, please visit https://dinisnoise.org/
*/



#include "countries.h"
#include "vector2d.h"
#include <vector>
#include <fstream>
#include <algorithm>
#include "console.h"
using namespace std;

extern ofstream dlog;

extern string user_data_dir;
extern string country_data_dir;
extern const int MILLION;

extern console cons;

bool area::operator< (const area& rhs) const {
 return num_vertices > rhs.num_vertices;
}

countries::countries () {
  name = "Countries";
  id = -1;
  p_cur_country = 0;
  area_id = 0;
  change_curve_name = 1;
}

countries::~countries () {
  widget_save ("d_countries", ctrls);
  save_params ();
}

void countries::load_params () {
  ifstream f (make_fname().c_str(), ios::in);
  string ignore;
  float step;
  f >> ignore >> id >> ignore >> area_id >> ignore >> step;
  sp_step.set_value (step);
  load_country (index[id]);
}

void countries::save_params () {
  ofstream f (make_fname().c_str(), ios::out);
  if (f) {
    f << "id " << id << endl;
    f << "area_id " << area_id << endl;
    f << "step " << int(sp_step.f_value) << endl;
  }
}

void countries::load_index () {
  string fname (country_data_dir + "index");
  ifstream f (fname.c_str(), ios::in);
  if (!f) {
    dlog << "couldnt read from : " << fname << endl;
    return;
  }
  f >> num_countries;
  for (int i = 0; i < num_countries; ++i) {
    f >> fname;
    index.push_back (fname);
  }
  sort (index.begin (), index.end());
}


void countries::setup () {

  plugin::setup ();

  load_index ();

  widget* _ctrls [] = {&ol_country, &ol_area, &sp_step, &lf_search};
  for (int i = 0; i < 4; ++i) ctrls.push_back (_ctrls[i]);

  num_ctrls = ctrls.size ();

  lf_search.set_text ("Country?");
  lf_search.set_listener (this);
  lf_search.fld.expr = 0;

  ol_country.set_text ("Country = ");
  ol_country.set_listener (this);
  ol_country.set_click_repeat (1);

  ol_area.set_listener (this);
  ol_area.set_click_repeat (1);
  ol_area.set_text ("Area = ");

  sp_step.set ("Step", 1, 1, MILLION, this, 0);

  widget_load ("d_countries", ctrls);

  load_params ();
  lf_search.fld.set_text (index[id]);

}

void countries::render () {
  if (p_cur_country) {
    points.clear ();
    area& a0 = p_cur_country->areas[area_id];
    float a0x = a0.x[0], a0y = a0.y[0];
    point<float> pa0 (a0x, a0y);
    points.push_back (pa0);
    for (int i = 1, j = a0.num_vertices - 1, di = sp_step.f_value; i < j; i += di) points.push_back (point<float>(a0.x[i], a0.y[i]));
    points.push_back (pa0);
    gen_pts ();
    ss.str("");
    ss << p_cur_country->name;
  }
}

country* countries::load_country (const string& which) {
  country& c = the_countries [which];
  if (c.num_areas ==  0) {
    string fname (country_data_dir + which);
    ifstream f (fname.c_str(), ios::in);
    if (!f) {
      dlog << "couldnt load from : " << fname << endl;
      return 0;
    }
    c.name = which;
    string ignore;
    while (!f.eof()) {
      f >> ignore >> c.num_areas;
      for (int i = 0; i < c.num_areas; ++i) {
        c.areas.push_back (area());
        area& ai = c.areas[i];
        f >> ignore >> ai.num_vertices;
        float l, b, r, t; f >> ignore >> l >> b >> r >> t;
        ai.bbox (l, b, r, t);
        for (int p = 0; p < ai.num_vertices; ++p) {
          float x, y; f >> x >> y;
          ai.x.push_back (x);
          ai.y.push_back (y);
        }
      }
    }
  }
  p_cur_country = &c;
  set_country (which);
  return &c;
}

void countries::picked (label& lbl, int dir) {
  if (&lbl == &ol_country.option) {
    id += dir;
    if (id < 0) id = num_countries - 1; else if (id >= num_countries) id = 0;
    string name (index[id]);
    load_country (name);
  } else if (&lbl == &ol_area.option) {
    if (p_cur_country) {
      area_id += dir;
      render_area ();
    }
  }
}

void countries::changed (field& f) {
  if (&f == &lf_search.fld) {
    string name (f.text);
        for (int i = 0, j = name.size (); i < j; ++i) if (name[i] == ' ') name[i]= '_';
    //for (auto& i : name) if (i == ' ') i = '_';
    int nid = find_id (name);
    if (nid == -1) {
      cons << console::red << "Couldnt find the country " << name << eol;
      if (name == "") f.set_text (index[id]);
    } else {
      id = nid;
      load_country (name);
    }
  } else {
    render ();
    if (cb_auto_apply.state) clicked (b_apply);
  }
}

void countries::render_area () {
  if (area_id < 0) area_id = p_cur_country->num_areas - 1; else if (area_id >= p_cur_country->num_areas) area_id = 0;
  stringstream ss; ss << "Area " << (area_id+1) << " of " << p_cur_country->num_areas;
  ol_area.set_text (ss.str());
  render ();
  if (cb_auto_apply.state) clicked (b_apply);
}

void countries::set_country (const string& name) {
  ol_country.set_text (name);
  lf_search.set_text (name);
  area_id = 0;
  render_area ();
}

int countries::find_id (const string& name) {
  for (int i = 0, j = index.size (); i < j; ++i) {
    if (index[i] == name) return i;
  }
  return -1;
}

void area::calc_bbox () {
  if (num_vertices) {
    float xmin = x[0], ymin = y[0], xmax = xmin, ymax = ymin;
    for (int i = 1, j = num_vertices; i < j; ++i) {
      float xi = x[i], yi = y[i];
      if (xi < xmin) xmin = xi; else if (xi > xmax) xmax = xi;
      if (yi < ymin) ymin = yi; else if (yi > ymax) ymax = yi;
    }
    bbox (xmin, ymin, xmax, ymax);
  }
}

void area::normalise () {
  float aspect_ratio = bbox.width * 1. / bbox.height;
  float xw = aspect_ratio * 2.0f, xwh = xw / 2.0f;
  for (int i = 0, j = num_vertices; i < j; ++i) {
    float xi = x[i], yi = y[i];
    float fx = (xi - bbox.left) * bbox.width_1;
    float fy = (yi - bbox.bottom) * bbox.height_1;
    float xj = -xwh + fx * xw;
    float yj = -1 + fy * 2.0f;
    x[i] = xj;
    y[i] = yj;
  }
  bbox (-xwh, -1.0f, xwh, 1.0f);
}