#ifndef __RINEX_H__ #define __RINEX_H__ /** * GPSデータの交換に標準的なRINEXファイルについて記述 * */ #include #include #include #include #include #include #include #include #include #include "GPS.h" class RINEX_Reader { public: typedef std::string string; typedef std::stringstream stringstream; typedef std::map header_t; protected: header_t _header; std::istream &src; bool _has_next; public: RINEX_Reader( std::istream &in, string &(*modify_header)(string &, string &) = NULL) : src(in), _has_next(false){ if(src.fail()){return;} char buf[256]; // ヘッダの読み出し while(!src.eof()){ src.getline(buf, sizeof(buf)); string content(buf); string label(content, 60, 20); { int real_length(label.find_last_not_of(' ') + 1); if(real_length < label.length()){ label = label.substr(0, real_length); } } //cout << label << " (" << label.length() << ")" << endl; if(label.find("END OF HEADER") == 0){break;} content = content.substr(0, 60); if(modify_header){content = modify_header(label, content);} if(_header.find(label) == _header.end()){ _header[label] = content; }else{ _header[label].append(content); // ある場合は追加する } } } virtual ~RINEX_Reader(){_header.clear();} header_t &header() {return _header;} bool has_next() const {return _has_next;} }; template struct RINEX_Nav { typedef typename GPS_SpaceNode::Satellite::Ephemeris ephemeris_t; struct SatelliteInfo { unsigned int svid; FloatT t_ot; ///< 送信時刻[s] ephemeris_t ephemeris; }; }; template class RINEX_Nav_Reader : public RINEX_Reader { protected: typedef RINEX_Nav model_t; typedef RINEX_Nav_Reader self_t; typedef RINEX_Reader super_t; public: typedef typename model_t::ephemeris_t ephemeris_t; typedef typename model_t::SatelliteInfo SatelliteInfo; protected: SatelliteInfo info; static string &modify_header(string &label, string &content){ if((label.find("ION ALPHA") == 0) || (label.find("ION BETA") == 0) || (label.find("DELTA-UTC: A0,A1,T,W") == 0)){ for(int pos(0); (pos = content.find("D", pos)) != string::npos; ){ content.replace(pos, 1, "E"); } } return content; } void seek_next() { char buf[256]; for(int i = 0; (i < 8) && (super_t::src.good()); i++){ if(super_t::src.getline(buf, sizeof(buf)).fail()){return;} string line_data(buf); for(int pos(0); (pos = line_data.find("D", pos)) != string::npos; ){ line_data.replace(pos, 1, "E"); } stringstream data(line_data); FloatT dummy; switch(i){ case 0: { data >> info.svid; info.ephemeris.svid = info.svid; struct tm t; data >> t.tm_year; // 年 data >> t.tm_mon; // 月 --(t.tm_mon); data >> t.tm_mday; // 日 data >> t.tm_hour; // 時 data >> t.tm_min; // 分 t.tm_sec = 0; GPS_Time gps_time(t); info.ephemeris.WN = gps_time.week; data >> info.ephemeris.t_oc; // 秒 info.ephemeris.t_oc += gps_time.seconds; data >> info.ephemeris.a_f0; data >> info.ephemeris.a_f1; data >> info.ephemeris.a_f2; break; } #define READ_AND_STORE(line_num, v0, v1, v2, v3) \ case line_num: { \ FloatT v; \ data >> v; v0 = v; \ data >> v; v1 = v; \ data >> v; v2 = v; \ data >> v; v3 = v; \ break; \ } READ_AND_STORE(1, info.ephemeris.iode, info.ephemeris.c_rs, info.ephemeris.delta_n, info.ephemeris.m0); READ_AND_STORE(2, info.ephemeris.c_uc, info.ephemeris.e, info.ephemeris.c_us, info.ephemeris.sqrt_A); READ_AND_STORE(3, info.ephemeris.t_oe, info.ephemeris.c_ic, info.ephemeris.Omega0, info.ephemeris.c_is); READ_AND_STORE(4, info.ephemeris.i0, info.ephemeris.c_rc, info.ephemeris.omega, info.ephemeris.dot_Omega0); READ_AND_STORE(5, info.ephemeris.dot_i0, dummy, info.ephemeris.WN, dummy); READ_AND_STORE(6, info.ephemeris.URA, info.ephemeris.SV_health, info.ephemeris.t_GD, info.ephemeris.iodc); READ_AND_STORE(7, info.t_ot, info.ephemeris.fit_interval, dummy, dummy); #undef READ_AND_STORE } } if(info.ephemeris.fit_interval == 0){ info.ephemeris.fit_interval = 4 * 60 * 60; // 最低4時間は有効 } super_t::_has_next = true; } public: RINEX_Nav_Reader(std::istream &in) : super_t(in, self_t::modify_header) { seek_next(); } ~RINEX_Nav_Reader(){} SatelliteInfo next() { SatelliteInfo current(info); super_t::_has_next = false; seek_next(); return current; } /** * 電離層遅延係数を取得し、セットする * * @return 成功した場合true、それ以外false */ bool extract_iono_coef(GPS_SpaceNode &space_node) const { if(_header.find("ION ALPHA") != _header.end()){ stringstream sstr(const_cast(&(_header)) ->operator[]("ION ALPHA")); sstr >> space_node.iono_coef().alpha0; sstr >> space_node.iono_coef().alpha1; sstr >> space_node.iono_coef().alpha2; sstr >> space_node.iono_coef().alpha3; }else{ return false; } if(_header.find("ION BETA") != _header.end()){ stringstream sstr(const_cast(&(_header)) ->operator[]("ION BETA")); sstr >> space_node.iono_coef().beta0; sstr >> space_node.iono_coef().beta1; sstr >> space_node.iono_coef().beta2; sstr >> space_node.iono_coef().beta3; }else{ return false; } return true; } }; template struct RINEX_Observe { struct ObservedItem { GPS_Time t_epoc; unsigned event_flag; FloatT receiver_clock_error; typedef struct { FloatT observed; unsigned lli, ss; } data_t; typedef std::vector data_1sat_t; typedef std::map sat_data_t; sat_data_t sat_data; }; }; template class RINEX_Observe_Reader : public RINEX_Reader { protected: typedef RINEX_Observe model_t; typedef RINEX_Observe_Reader self_t; typedef RINEX_Reader super_t; public: typedef typename model_t::ObservedItem ObservedItem; protected: std::vector types_of_observe; ObservedItem item; static string &modify_header(string &label, string &content){ return content; } void seek_next() { if(types_of_observe.size() == 0){return;} char buf[256]; std::queue sat_list; item.sat_data.clear(); while(true){ // エポック行の読込み { unsigned num_of_followed_data(0); if(super_t::src.getline(buf, sizeof(buf)).fail()){return;} string data_line(buf); stringstream(data_line.substr(26, 3)) >> item.event_flag; // イベントフラグ stringstream(data_line.substr(29, 3)) >> num_of_followed_data; // 衛星(flag = 0/1) or 行数(0/1以外) if(item.event_flag >= 2){ while(num_of_followed_data--){ if(super_t::src.getline(buf, sizeof(buf)).fail()){return;} } continue; } stringstream data(data_line); // エポック時刻の抽出 struct tm t; data >> t.tm_year; // 年 data >> t.tm_mon; // 月 --(t.tm_mon); data >> t.tm_mday; // 日 data >> t.tm_hour; // 時 data >> t.tm_min; // 分 t.tm_sec = 0; item.t_epoc = GPS_Time(t); FloatT v; data >> v; // 秒 item.t_epoc += v; // 受信機クロック誤差 stringstream(data_line.substr(68)) >> item.receiver_clock_error; int prn; for(int i(0); num_of_followed_data > 0; i++, num_of_followed_data--){ if(i == 12){ // 12衛星以上の場合は次の行 if(super_t::src.getline(buf, sizeof(buf)).fail()){return;} data_line = string(buf); i = 0; } stringstream(data_line.substr(33 + (i * 3), 2)) >> prn; switch(data_line[32 + (i * 3)]){ case ' ': case 'G': break; // NAVSTAR case 'R': prn += 200; break; // GLONASS case 'S': prn += 100; break; // SBAS default: prn += 300; } sat_list.push(prn); //cerr << prn << endl; } } // 衛星ごとの観測データの入込み while(!sat_list.empty()){ int prn(sat_list.front()); sat_list.pop(); item.sat_data[prn]; string data_line; for(int i(0); i < types_of_observe.size(); i++){ int offset_index(i % 5); if(offset_index == 0){ if(super_t::src.getline(buf, sizeof(buf)).fail()){return;} data_line = string(buf); } typename ObservedItem::data_t data; string s(data_line.substr(offset_index * 16, 16)); stringstream ss(s); ss >> data.observed; data.lli = data.ss = 0; if(s.size() >= 15){unsigned i(s[14] - '0'); if(i < 10){data.lli = i;}} if(s.size() >= 16){unsigned i(s[15] - '0'); if(i < 10){data.ss = i;}} //cerr << data.observed << ", " << data.lli << "," << data.ss << endl; item.sat_data[prn].push_back(data); } } break; } super_t::_has_next = true; } public: RINEX_Observe_Reader(std::istream &in) : super_t(in, self_t::modify_header), types_of_observe() { if(super_t::_header.find("# / TYPES OF OBSERV") != super_t::_header.end()){ stringstream data(super_t::_header["# / TYPES OF OBSERV"]); unsigned num_types_of_observe; data >> num_types_of_observe; while(num_types_of_observe){ string param_name; data >> param_name; if(!data.good()){break;} types_of_observe.push_back(param_name); num_types_of_observe--; } if(num_types_of_observe == 0){ seek_next(); }else{ types_of_observe.clear(); } } } ~RINEX_Observe_Reader(){} ObservedItem next() { ObservedItem current(item); super_t::_has_next = false; seek_next(); return current; } /** * データ行において、ラベルに対応するインデックスを返す * 見つからなかった場合は-1が返る * */ int observed_index(const string &label) const { int res(distance(types_of_observe.begin(), find(types_of_observe.begin(), types_of_observe.end(), label))); return (res >= types_of_observe.size() ? -1 : res); } int observed_index(const char *label) const { return observed_index(string(label)); } }; class RINEX_Writer { public: typedef std::string string; typedef struct {const char *key, *value;} header_item_t; class header_t : public std::map { private: template static void write_header_item( std::ostream &out, const T1 &key, const T2 &value){ out << std::setw(60) << value; out << std::setw(20) << key << std::endl; } public: const header_item_t *mask; const int mask_size; header_t( const header_item_t *_mask = NULL, const int _mask_size = 0) : std::map(), mask(_mask), mask_size(_mask_size) {} ~header_t() {} friend std::ostream &operator<<(std::ostream &out, const header_t &header){ std::stringstream ss; ss << std::setfill(' ') << std::left; if(header.mask){ // マスクで並び替えをしつつ出力 for(int i(0); i < header.mask_size; i++){ header_t::const_iterator it(header.find(header.mask[i].key)); if(it != header.end()){ write_header_item( ss, header.mask[i].key, it->second); }else if(header.mask[i].value){ // デフォルト値 write_header_item( ss, header.mask[i].key, header.mask[i].value); } } }else{ for(header_t::const_iterator it(header.begin()); it != header.end(); ++it){ for(int index(0); index < it->second.length(); index += 60){ write_header_item( ss, it->first.substr(0, 20), it->second.substr(index, 60)); } } } write_header_item(ss, "END OF HEADER", ""); return out << ss.str(); } }; protected: header_t _header; std::ostream &dist; public: RINEX_Writer( std::ostream &out, const header_item_t *header_mask = NULL, const int header_mask_size = 0) : _header(header_mask, header_mask_size), dist(out) { } virtual ~RINEX_Writer() {_header.clear();} header_t &header(){return _header;} template static std::string RINEX_Float( const FloatT &value, const int width = 19, const int precision = 12){ std::stringstream ss; ss << std::setfill(' ') << std::right << std::setw(width) << std::setprecision(precision) << std::fixed << value; return ss.str(); } template static std::string RINEX_FloatD( const FloatT &value, const int width = 19, const int precision = 12){ int w(std::max(width, precision + 6)); std::stringstream ss; ss << std::setprecision(precision - 1) << std::scientific << (value * 1E1); string s(ss.str()); //std::cout << s << std::endl; // -1.2345E+06 // 一番上の桁と小数点を入れ替え => -.12345E+06 int index(s[0] == '-' ? 1 : 0); s[index + 1] = s[index + 0]; s[index + 0] = '.'; // EをDに置換 => -.12345D+06 s[index + precision + 1] = 'D'; // 指数部の調整(2桁以上の場合は強制的に捨てる) s.erase(index + precision + 3, s.size() - (index + precision + 5)); ss.str(""); ss << std::setfill(' ') << std::right << std::setw(w) << s; return ss.str(); } template static std::string RINEX_Value( const T &value, const int width = 6){ std::stringstream ss; ss << std::setfill(' ') << std::right << std::setw(width) << value; return ss.str(); } void leap_seconds(const int seconds){ std::stringstream ss; ss << RINEX_Value(seconds, 6); _header["LEAP SECONDS"] = ss.str(); } }; template class RINEX_Nav_Writer : public RINEX_Writer { public: typedef RINEX_Nav model_t; typedef RINEX_Nav_Writer self_t; typedef RINEX_Writer super_t; protected: using super_t::RINEX_Float; using super_t::RINEX_FloatD; using super_t::RINEX_Value; using super_t::_header; using super_t::dist; public: static const super_t::header_item_t default_header[]; static const int default_header_size; void ion_alpha( const FloatT &a0, const FloatT &a1, const FloatT &a2, const FloatT &a3){ std::stringstream ss; ss << " " << RINEX_FloatD(a0, 12, 4) << RINEX_FloatD(a1, 12, 4) << RINEX_FloatD(a2, 12, 4) << RINEX_FloatD(a3, 12, 4); _header["ION ALPHA"] = ss.str(); } void ion_beta( const FloatT &b0, const FloatT &b1, const FloatT &b2, const FloatT &b3){ std::stringstream ss; ss << " " << RINEX_FloatD(b0, 12, 4) << RINEX_FloatD(b1, 12, 4) << RINEX_FloatD(b2, 12, 4) << RINEX_FloatD(b3, 12, 4); _header["ION BETA"] = ss.str(); } RINEX_Nav_Writer(std::ostream &out) : super_t(out, default_header, default_header_size) {} ~RINEX_Nav_Writer(){} self_t &operator<<(const typename model_t::SatelliteInfo &data){ std::stringstream buf; // PRN buf << RINEX_Value(data.svid % 100, 2); // 時刻 { GPS_Time gps_time(data.ephemeris.WN, data.ephemeris.t_oc); struct tm t(gps_time.c_tm()); FloatT sec_f(gps_time.seconds), sec_i; sec_f = std::modf(sec_f, &sec_i); buf << (t.tm_year < 10 ? " 0" : " ") << t.tm_year << RINEX_Value(t.tm_mon + 1, 3) << RINEX_Value(t.tm_mday, 3) << RINEX_Value(t.tm_hour, 3) << RINEX_Value(t.tm_min, 3) << RINEX_Float(sec_f + t.tm_sec, 5, 1); } // 1行目の残り buf << RINEX_FloatD(data.ephemeris.a_f0, 19, 12) << RINEX_FloatD(data.ephemeris.a_f1, 19, 12) << RINEX_FloatD(data.ephemeris.a_f2, 19, 12) << std::endl; // 2行目 buf << string(3, ' ') << RINEX_FloatD(data.ephemeris.iode, 19, 12) << RINEX_FloatD(data.ephemeris.c_rs, 19, 12) << RINEX_FloatD(data.ephemeris.delta_n, 19, 12) << RINEX_FloatD(data.ephemeris.m0, 19, 12) << std::endl; // 3行目 buf << string(3, ' ') << RINEX_FloatD(data.ephemeris.c_uc, 19, 12) << RINEX_FloatD(data.ephemeris.e, 19, 12) << RINEX_FloatD(data.ephemeris.c_us, 19, 12) << RINEX_FloatD(data.ephemeris.sqrt_A, 19, 12) << std::endl; // 4行目 buf << string(3, ' ') << RINEX_FloatD(data.ephemeris.t_oe, 19, 12) << RINEX_FloatD(data.ephemeris.c_ic, 19, 12) << RINEX_FloatD(data.ephemeris.Omega0, 19, 12) << RINEX_FloatD(data.ephemeris.c_is, 19, 12) << std::endl; // 5行目 buf << string(3, ' ') << RINEX_FloatD(data.ephemeris.i0, 19, 12) << RINEX_FloatD(data.ephemeris.c_rc, 19, 12) << RINEX_FloatD(data.ephemeris.omega, 19, 12) << RINEX_FloatD(data.ephemeris.dot_Omega0, 19, 12) << std::endl; // 6行目 buf << string(3, ' ') << RINEX_FloatD(data.ephemeris.dot_i0, 19, 12) << RINEX_FloatD(0.0, 19, 12) << RINEX_FloatD(data.ephemeris.WN, 19, 12) << RINEX_FloatD(0.0, 19, 12) << std::endl; // 7行目 buf << string(3, ' ') << RINEX_FloatD(data.ephemeris.URA, 19, 12) << RINEX_FloatD(data.ephemeris.SV_health, 19, 12) << RINEX_FloatD(data.ephemeris.t_GD, 19, 12) << RINEX_FloatD(data.ephemeris.iodc, 19, 12) << std::endl; // 8行目 buf << string(3, ' ') << RINEX_FloatD(data.t_ot, 19, 12) << RINEX_FloatD(data.ephemeris.fit_interval, 19, 12) << RINEX_FloatD(0.0, 19, 12) << RINEX_FloatD(0.0, 19, 12) << std::endl; dist << buf.str(); return *this; } }; template const RINEX_Writer::header_item_t RINEX_Nav_Writer::default_header[] = { {"RINEX VERSION / TYPE", " 2 NAVIGATION DATA"}, {"COMMENT", NULL}, {"ION ALPHA", NULL}, {"ION BETA", NULL}, {"DELTA UTC: A0,A1,T,W ", NULL}, {"LEAP SECONDS", NULL}}; template const int RINEX_Nav_Writer::default_header_size = sizeof(RINEX_Nav_Writer::default_header) / sizeof(RINEX_Nav_Writer::default_header[0]); template class RINEX_Observe_Writer : public RINEX_Writer { public: typedef RINEX_Observe model_t; typedef RINEX_Observe_Writer self_t; typedef RINEX_Writer super_t; protected: using super_t::RINEX_Float; using super_t::RINEX_FloatD; using super_t::RINEX_Value; using super_t::_header; using super_t::dist; public: static const header_item_t default_header[]; static const int default_header_size; void pgm_runby_date( const std::string &pgm, const std::string &runby, const struct tm &t){ // ex) "XXRINEXO V9.9 AIUB 12-SEP-90 12:43" char buf[20] = {0}; std::strftime(buf, sizeof(buf) - 1, "%d-%b-%y %H:%M", &t); std::stringstream ss; ss << std::setfill(' ') << std::left << std::setw(20) << pgm.substr(0, 20) << std::setw(20) << runby.substr(0, 20) << buf; _header["PGM / RUN BY / DATE"] = ss.str(); } void maker_name( const std::string &name){ _header["MARKER NAME"] = name.substr(0, 60); } void observer_agency( const std::string &observer, const std::string &agency){ // ex) "BILL SMITH ABC INSTITUTE" std::stringstream ss; ss << std::setfill(' ') << std::left << std::setw(20) << observer.substr(0, 20) << std::setw(20) << agency.substr(0, 20); _header["OBSERVER / AGENCY"] = ss.str(); } void receiver_spec( const std::string &num, const std::string &type, const std::string &vers){ // ex) "X1234A123 XX ZZZ" std::stringstream ss; ss << std::setfill(' ') << std::left << std::setw(20) << num.substr(0, 20) << std::setw(20) << type.substr(0, 20) << std::setw(20) << vers.substr(0, 20); _header["REC # / TYPE / VERS"] = ss.str(); } void antenna_spec( const std::string &num, const std::string &type){ // ex) "234 YY" std::stringstream ss; ss << std::setfill(' ') << std::left << std::setw(20) << num.substr(0, 20) << std::setw(20) << type.substr(0, 20); _header["ANT # / TYPE"] = ss.str(); } void wavelength_fact( const int l1, const int l2){ // ex) " 1 1" std::stringstream ss; ss << RINEX_Value(l1, 6) << RINEX_Value(l2, 6); _header["WAVELENGTH FACT L1/2"] = ss.str(); } void approx_position( const FloatT &x, const FloatT &y, const FloatT &z){ std::stringstream ss; ss << RINEX_Float(x, 14, 4) << RINEX_Float(y, 14, 4) << RINEX_Float(z, 14, 4); _header["APPROX POSITION XYZ"] = ss.str(); } void antenna_delta_hew( const FloatT &h, const FloatT &e, const FloatT &w){ std::stringstream ss; ss << RINEX_Float(h, 14, 4) << RINEX_Float(e, 14, 4) << RINEX_Float(w, 14, 4); _header["ANTENNA: DELTA H/E/W"] = ss.str(); } void types_of_obs( const char *type_list[], const int list_size){ std::stringstream ss; ss << RINEX_Value(list_size, 6); for(int i(0); i < list_size; i++){ ss << RINEX_Value( std::string(type_list[i]).substr(0, 6), 6); } _header["# / TYPES OF OBSERV"] = ss.str(); } void interval(const FloatT &seconds){ std::stringstream ss; ss << RINEX_Float(seconds, 6, 4); _header["INTERVAL"] = ss.str(); } void interval(const int seconds){ std::stringstream ss; ss << RINEX_Value(seconds, 6); _header["INTERVAL"] = ss.str(); } void insert_header_time_item( const char *label, const struct tm &t, const FloatT &rest_second = 0, const bool is_gps_time = true){ std::stringstream ss; if(t.tm_year < 80){ ss << RINEX_Value(2000 + t.tm_year, 6); }else{ ss << RINEX_Value(1900 + t.tm_year, 6); } ss << RINEX_Value(t.tm_mon + 1, 6); ss << RINEX_Value(t.tm_mday, 6); ss << RINEX_Value(t.tm_hour, 6); ss << RINEX_Value(t.tm_min, 6); ss << RINEX_Float(rest_second + t.tm_sec, 12, 6); if(is_gps_time){ ss << RINEX_Value("GPS", 9); } _header[label] = ss.str(); } void insert_header_time_item( const char *label, const GPS_Time &t){ FloatT sec_f(t.seconds), sec_i; sec_f = std::modf(sec_f, &sec_i); insert_header_time_item(label, t.c_tm(), sec_f, true); } void first_obs( const struct tm &t, const double rest_second = 0, const bool is_gps_time = true){ insert_header_time_item("TIME OF FIRST OBS", t, rest_second, is_gps_time); } void first_obs(const GPS_Time &t){ insert_header_time_item("TIME OF FIRST OBS", t); } void last_obs( const struct tm &t, const double rest_second = 0, const bool is_gps_time = true){ insert_header_time_item("TIME OF LAST OBS", t, rest_second, is_gps_time); } void last_obs(const GPS_Time &t){ insert_header_time_item("TIME OF LAST OBS", t); } RINEX_Observe_Writer(std::ostream &out) : super_t(out, default_header, default_header_size) {} ~RINEX_Observe_Writer(){} self_t &operator<<(const typename model_t::ObservedItem &data){ typedef typename model_t::ObservedItem::sat_data_t sat_data_t; std::stringstream top, rest; { // 時刻の処理 struct tm t(data.t_epoc.c_tm()); FloatT sec_f(data.t_epoc.seconds), sec_i; sec_f = std::modf(sec_f, &sec_i); if(t.tm_year < 10){ top << " 0" << t.tm_year; }else{ top << ' ' << t.tm_year; } top << RINEX_Value(t.tm_mon + 1, 3) << RINEX_Value(t.tm_mday, 3) << RINEX_Value(t.tm_hour, 3) << RINEX_Value(t.tm_min, 3) << RINEX_Float(sec_f + t.tm_sec, 11, 7); } top << RINEX_Value(0, 3); // Epoch flag top << RINEX_Value(data.sat_data.size(), 3); // 衛星数 int index(0); for(typename sat_data_t::const_iterator it(data.sat_data.begin()); it != data.sat_data.end(); ++it, ++index){ // 衛星の列挙 // 1行に12衛星までしかかけない、行を送る if(index == 12){ // 受信クロック誤差 top << RINEX_Float(data.receiver_clock_error, 12, 9); } if((index % 12 == 0) && (index > 0)){ top << std::endl << string(32, ' '); } // リストにPRN番号を書く int prn(it->first); if(prn < 100){ top << 'G'; }else if(prn < 200){ top << 'S'; }else if(prn < 300){ top << 'R'; }else{ top << ' '; } top << RINEX_Value(prn % 100, 2); // 観測データを記述 int index2(0); for(typename sat_data_t::mapped_type::const_iterator it2(it->second.begin()); it2 != it->second.end(); ++it2, ++index2){ if((index2 % 5 == 0) && (index2 > 0)){ rest << std::endl; } rest << RINEX_Float(it2->observed, 14, 3); if(it2->lli){rest << (it2->lli % 10);}else{rest << ' ';} if(it2->ss){rest << (it2->ss % 10);}else{rest << ' ';} } rest << std::endl; } if(index <= 12){ top << string((12 - index) * 3, ' '); // 受信クロック誤差 top << RINEX_Float(data.receiver_clock_error, 12, 9); } top << std::endl; dist << top.str() << rest.str(); return *this; } }; template const RINEX_Writer::header_item_t RINEX_Observe_Writer::default_header[] = { {"RINEX VERSION / TYPE", " 2 OBSERVATION DATA"}, {"PGM / RUN BY / DATE", "XXRINEXO V9.9 AIUB 12-SEP-90 12:43"}, {"COMMENT", NULL}, {"MARKER NAME", "A 9080"}, {"MARKER NUMBER", NULL}, {"OBSERVER / AGENCY", "BILL SMITH ABC INSTITUTE"}, {"REC # / TYPE / VERS", "X1234A123 XX ZZZ"}, {"ANT # / TYPE", "234 YY"}, {"APPROX POSITION XYZ", " -3947762.7496 3364399.8789 3699428.5111"}, {"ANTENNA: DELTA H/E/W", " 0.0000 0.0000 0.0000"}, {"WAVELENGTH FACT L1/2", " 1 1"}, {"# / TYPES OF OBSERV", " 4 P1 L1 L2 P2"}, {"INTERVAL", " 1"}, {"TIME OF FIRST OBS", " 1990 3 24 13 10 36.000000"}, {"TIME OF LAST OBS", NULL}, {"# OF SATELLITES", NULL}, {"PRN / # OF OBS", NULL}}; template const int RINEX_Observe_Writer::default_header_size = sizeof(RINEX_Observe_Writer::default_header) / sizeof(RINEX_Observe_Writer::default_header[0]); #endif // __RINEX_H__