最近,帮助一个师妹实现了地理坐标的欧式距离计算,其数据存储在文本文件中,然后很多类似的文本文件组成一个文件夹路径,本程序源码主要实现了C++文件便利,存储,以及计算相关功能的实现。下边的贴图是数据的基本格式:文件的前六行是数据说明文件,在处理的时候需要略过,正文数据意义为:纬度,经度,无意义,高程,离1899年的天数,日期和时间。需要做的操作如下:
1. 从文件中读出数据到一个类中,定义为User,
2. 给定文件夹路径,遍历所有文件
3. 文件的命名是日期,需要按照日期排序
4. 相邻的两个文件求得欧式距离,取得最大值
5. 获取所有相邻文件的最大值
假设文件有1,2,3,4.则12之间相应求解欧式距离,取得所有欧式距离的最大值,与此类似,取得34最大值,最后取得1234最大值。
关于boost库的安装参照本人前边的博客。
Geolife trajectory
WGS 84
Altitude is in Feet
Reserved 3
0,2,255,My Track,0,0,2,8421376
0
39.984702,116.318417,0,492,39744.1201851852,2008-10-23,02:53:04
39.984683,116.31845,0,492,39744.1202546296,2008-10-23,02:53:10
39.984686,116.318417,0,492,39744.1203125,2008-10-23,02:53:15
39.984688,116.318385,0,492,39744.1203703704,2008-10-23,02:53:20
39.984655,116.318263,0,492,39744.1204282407,2008-10-23,02:53:25
39.984611,116.318026,0,493,39744.1204861111,2008-10-23,02:53:30
39.984608,116.317761,0,493,39744.1205439815,2008-10-23,02:53:35
39.984563,116.317517,0,496,39744.1206018519,2008-10-23,02:53:40
39.984539,116.317294,0,500,39744.1206597222,2008-10-23,02:53:45
39.984606,116.317065,0,505,39744.1207175926,2008-10-23,02:53:50
39.984568,116.316911,0,510,39744.120775463,2008-10-23,02:53:55
User.hpp:实现了操作符重载,
// // User.hpp // Test // // Created by 秦传庆 on 15/10/23. // Copyright © 2015年 秦传庆. All rights reserved. // #ifndef User_hpp #define User_hpp #include <boost/date_time/gregorian/gregorian.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <sstream> namespace gregorianDate = boost::gregorian; using namespace boost::posix_time; using namespace std; /* 39.984702,116.318417,0,492,39744.1201851852,2008-10-23,02:53:04 39.984683,116.31845,0,492,39744.1202546296,2008-10-23,02:53:10 39.984686,116.318417,0,492,39744.1203125,2008-10-23,02:53:15 39.984688,116.318385,0,492,39744.1203703704,2008-10-23,02:53:20 39.984655,116.318263,0,492,39744.1204282407,2008-10-23,02:53:25 39.984611,116.318026,0,493,39744.1204861111,2008-10-23,02:53:30 39.984608,116.317761,0,493,39744.1205439815,2008-10-23,02:53:35 */ class User { private: double latitude; double longitude; int nonsense; int altitude; double daysince18991230; gregorianDate::date date; time_duration time; //ptime date; public: friend ostream &operator<<(ostream &os, const User &c); friend istream &operator>>(istream &is, User &c); /*Java, setter and geter*/ void setLatitude(double latitude); double getLatitude(); void setLongitude(double longitude); double getLongitude(); void setNonsense(int nonsense); int getNonsense(); void setAltitude(int altitude); int getAltitude(); void setDaysince18991230(double daysince18991230); double getDaysince18991230(); void setDate(string date); void setDate(gregorianDate::date date); gregorianDate::date getDate(); void setTime(string time); void setTime(time_duration time); time_duration getTime(); }; template<class out, class in> out ConvertDataType(const in& a); #endif /* User_hpp */
<pre name="code" class="cpp">// // User.cpp // Test // // Created by 秦传庆 on 15/10/23. // Copyright © 2015年 秦传庆. All rights reserved. // #include "User.hpp" void User::setLatitude(double latitude) { this->latitude = latitude; } double User::getLatitude() { return latitude; } void User::setLongitude(double longitude) { this->longitude = longitude; } double User::getLongitude() { return longitude; } void User::setNonsense(int nonsense) { this->nonsense = nonsense; } int User::getNonsense() { return nonsense; } void User::setAltitude(int altitude) { this->altitude = altitude; } int User::getAltitude() { return altitude; } void User::setDaysince18991230(double daysince18991230) { this->daysince18991230 = daysince18991230; } double User::getDaysince18991230() { return daysince18991230; } void User::setDate(string date) { this->setDate(gregorianDate::from_string(date)); } void User::setDate(gregorianDate::date date){ this->date = date; } gregorianDate::date User::getDate() { return date; } void User::setTime(string time) { this->setTime(duration_from_string(time)); } void User::setTime(time_duration time){ this->time = time; } time_duration User::getTime() { return time; } ostream &operator<<(ostream &out, const User &user) { ostream::fmtflags curr_fmt = out.flags(); out.precision(10); out << user.latitude << ","; out << user.longitude << ","; out << user.nonsense << ","; out << user.altitude << ","; out << user.daysince18991230 << ","; out << gregorianDate::to_simple_string(user.date) << ","; out << to_simple_string(user.time) << endl; out.flags(curr_fmt); return out; } /*char temp used to go over the ","*/ istream &operator>>(istream &in, User &user) { char temp; string temp_string; istream::fmtflags curr_fmt = in.flags(); in >> user.latitude; in >> temp; in >> user.longitude; in >> temp; in >> user.nonsense; in >> temp; in >> user.altitude; in >> temp; in >> user.daysince18991230; in >> temp; in >> temp_string; if ("" == temp_string){ return in; } size_t pos = temp_string.find_first_of(","); user.date = gregorianDate::from_string(temp_string.substr(0, pos)); user.time = duration_from_string(temp_string.substr(pos + 1, temp_string.size())); in.flags(curr_fmt); return in; }
// // FileIter.hpp // Test // // Created by 秦传庆 on 15/10/23. // Copyright © 2015年 秦传庆. All rights reserved. // #ifndef FileIter_hpp #define FileIter_hpp #include <iostream> #include <boost/filesystem.hpp> #include <algorithm> #include "Utils.hpp" using namespace std; using namespace boost::filesystem; class FileIter { private: string path; vector<string> data; public: FileIter(string path); void walk(); void walk(string path); vector<string> getVector(); friend bool compare(string file1, string file2); private: void walk(boost::filesystem::path p); }; bool compare(string file1, string file2); #endif /* FileIter_hpp */
// // FileIter.cpp // Test // // Created by 秦传庆 on 15/10/23. // Copyright © 2015年 秦传庆. All rights reserved. // #include "FileIter.hpp" FileIter::FileIter(string path) { this->path = path; } void FileIter::walk() { walk(path); } void FileIter::walk(string path) { auto p = boost::filesystem::path(path); walk(p); sort(data.begin(), data.end(), compare); //PrintVector(data); } void FileIter::walk(boost::filesystem::path p) { try { if (exists(p)) { if (is_regular_file(p) && !boost::filesystem::is_empty(p)) { //cout << p << " size is " << file_size(p) << '\n'; data.push_back(p.string()); }else if (is_directory(p)) { //cout << p << " is a directory containing:\n"; for (directory_entry& x : directory_iterator(p)) { walk(x.path()); } }else { cout << p << " exists, but is not a regular file or directory\n"; } }else { cout << p << " does not exist\n"; } }catch (const filesystem_error& ex) { cout << ex.what() << '\n'; } } vector<string> FileIter::getVector() { return data; } bool compare(string file1, string file2){ file1 = file1.substr(file1.find_last_of("/") + 1, 14); file2 = file2.substr(file2.find_last_of("/") + 1, 14); //cout << file1 << "," << file2 << endl; return file1 < file2; }
Utils.hpp : 实现了一些功能调试函数,文件是否打开成功,打印容器内容,易于查看。
// // Utils.hpp // Test // // Created by 秦传庆 on 15/10/25. // Copyright © 2015年 秦传庆. All rights reserved. // #ifndef Utils_hpp #define Utils_hpp #define BOOST_LOG_DYN_LINK #include <fstream> #include <vector> #include <iostream> #include <sstream> #include <boost/lexical_cast.hpp> using namespace boost; using namespace std; bool FileExist(const fstream& in); template<class out, class in> out ConvertDataType(const in& a) { /* std::stringstream temp; temp<<a; out b; temp>>b; return b; */ return lexical_cast<out>(a); } template<typename T> void PrintVector(const vector<T>& data); template<typename T> string VectorToString(const vector<T>& data){ string content; for (auto& temp : data){ content.append(ConvertDataType<std::string>(temp)); } return content; } #include "TestUnit.cpp" #endif /* Utils_hpp */
// // Utils.cpp // Test // // Created by 秦传庆 on 15/10/25. // Copyright © 2015年 秦传庆. All rights reserved. // #include "Utils.hpp" bool FileExist(fstream& in){ if (!in){ std::cerr << "unable open the file, please check it." << std::endl; return false; } return true; }
// // TestUnit.cpp // Test // // Created by 秦传庆 on 15/10/23. // Copyright © 2015年 秦传庆. All rights reserved. // #include <iostream> #include <vector> #include<fstream> using namespace std; template<typename T> void PrintVector(vector<T> data) { cout << "{" ; for (auto item : data) { cout << item << ","; } cout << "}" ; cout << endl; }
// // SpaceDistance.hpp // Test // // Created by 秦传庆 on 15/10/25. // Copyright © 2015年 秦传庆. All rights reserved. // #ifndef SpaceDistance_hpp #define SpaceDistance_hpp #include "User.hpp" #include "Utils.hpp" #include "FileIter.hpp" #include "Logger.hpp" #include <iostream> #include <fstream> #include <vector> #include <cmath> #include <algorithm> #include <boost/timer.hpp> using namespace std; class SpaceDistance{ private: boost::timer time; FileIter folder; vector<string> file_names; fstream file_stream; vector<User> data_original; vector<User> data_compare; //vector<vector<User>> data; istream_iterator<User> eof; vector<string>::size_type file_number; public: SpaceDistance(string path); double calculateDistance(); private: bool checkFileNumber(){ return true; } vector<User> getDataFromFile(string file_name); double calculateDistanceOfTwo(); void validateFiles(); }; #endif /* SpaceDistance_hpp */
// // SpaceDistance.cpp // Test // // Created by 秦传庆 on 15/10/25. // Copyright © 2015年 秦传庆. All rights reserved. // #include "SpaceDistance.hpp" using namespace std; SpaceDistance::SpaceDistance(string path):folder(path){ folder.walk(); file_names = folder.getVector(); //PrintVector(file_names); validateFiles(); file_number = file_names.size(); } double SpaceDistance::calculateDistance(){ double distanceOfTwo; double maxDistance; string msg; if (!checkFileNumber()){ return 0.0; } vector<double> distance; /* for (auto fileName:file_names){ data.push_back(getDataFromFile(fileName)); } */ for (auto i = 0; i < file_number - 1; i++) { time.restart(); data_original = getDataFromFile(file_names[i]); //data_original = data[i]; for (auto j = i + 1; j < file_number; j++){ data_compare = getDataFromFile(file_names[j]); //data_compare = data[j]; distanceOfTwo = calculateDistanceOfTwo(); distance.push_back(distanceOfTwo); //info_log(file_names[i]); msg.clear(); msg.append(file_names[i]); msg.append(","); msg.append(file_names[j]); msg.append(":"); msg.append(ConvertDataType<std::string>(distanceOfTwo)); BOOST_LOG_FUNCTION(); info_log(msg); } msg.clear(); msg.append("Time elapesd: "); msg.append(ConvertDataType<std::string>(time.elapsed())); BOOST_LOG_FUNCTION(); info_log(msg); } //PrintVector(distance); //BOOST_LOG_FUNCTION(); maxDistance = *max_element(distance.begin(), distance.end()); //info_log(maxDistance); return maxDistance; } vector<User> SpaceDistance::getDataFromFile(string file_name){ file_stream.open(file_name.c_str(), fstream::in); if (!FileExist(file_stream)) { return vector<User>(); } string temp; /* * below for cycle will go over 6 lines in each file. */ for(int i = 0; i < 6; i++){ getline(file_stream, temp); } istream_iterator<User> item_iter(file_stream); vector<User> data(item_iter, eof); file_stream.close(); file_stream.clear(); return data; } double SpaceDistance::calculateDistanceOfTwo(){ /* * here do math of the gero. */ vector<double> data; vector<double> temp; //auto length = data_original.size() > data_compare.size()? data_compare.size():data_original.size(); double x_original; double y_original; double x_compare; double y_compare; auto original_length = data_original.size(); auto compare_length = data_compare.size(); for (auto i = 0; i < original_length; i++){ x_original = data_original[i].getLongitude(); y_original = data_original[i].getLatitude(); temp.clear(); for (auto j = 0; j < compare_length; j++){ x_compare = data_compare[j].getLongitude(); y_compare = data_compare[j].getLatitude(); temp.push_back(sqrt(pow((x_original - x_compare), 2) + pow((y_original - y_compare), 2))); } //PrintVector(temp); data.push_back(*max_element(temp.begin(), temp.end())); } //PrintVector(data); //BOOST_LOG_FUNCTION(); //info_log(VectorToString(data)); return *max_element(data.begin(), data.end()); } void SpaceDistance::validateFiles(){ string extension_string = ".plt"; for (auto iter = file_names.begin(); iter != file_names.end();){ if (extension_string != (*iter).substr((*iter).size() - extension_string.size(), extension_string.size())){ file_names.erase(iter); } else { iter++; } } }Logger.hpp 日志记录系统
// // Logger.hpp // Test // // Created by 秦传庆 on 15/11/2. // Copyright © 2015年 秦传庆. All rights reserved. // #ifndef Logger_hpp #define Logger_hpp #define BOOST_LOG_DYN_LINK #include <iostream> #include <fstream> #include <boost/log/expressions.hpp> #include <boost/smart_ptr/shared_ptr.hpp> #include <boost/smart_ptr/make_shared_object.hpp> #include <boost/log/core.hpp> #include <boost/log/trivial.hpp> #include <boost/log/sinks/sync_frontend.hpp> #include <boost/log/sinks/text_file_backend.hpp> #include <boost/log/sinks/text_ostream_backend.hpp> #include <boost/log/utility/setup/file.hpp> #include <boost/log/utility/setup/common_attributes.hpp> #include <boost/log/sources/severity_logger.hpp> #include <boost/log/sources/record_ostream.hpp> #include <boost/log/sources/logger.hpp> #include <boost/core/null_deleter.hpp> #include <boost/log/sources/global_logger_storage.hpp> #include <boost/log/attributes/named_scope.hpp> #include <boost/log/support/date_time.hpp> #include <boost/log/detail/format.hpp> #include <boost/log/detail/thread_id.hpp> namespace logging = boost::log; namespace sinks = boost::log::sinks; namespace src = boost::log::sources; namespace expr = boost::log::expressions; namespace attrs = boost::log::attributes; namespace keywords = boost::log::keywords; using namespace logging::trivial; using namespace std; class Logger { public: static void init(); }; template<class T> void trace_log(const T& content) { src::severity_logger<severity_level> lg; BOOST_LOG_SEV(lg, logging::trivial::trace) << content; } template<class T> void debug_log(const T& content) { src::severity_logger<severity_level> lg; BOOST_LOG_SEV(lg, logging::trivial::debug) << content; } template<class T> void info_log(const T& content) { src::severity_logger<severity_level> lg; BOOST_LOG_SEV(lg, logging::trivial::info) << content; } template<class T> void warning_log(const T& content) { src::severity_logger<severity_level> lg; BOOST_LOG_SEV(lg, logging::trivial::warning) << content; } template<class T> void error_log(const T& content) { src::severity_logger<severity_level> lg; BOOST_LOG_SEV(lg, logging::trivial::error) << content; } template<class T> void fatal_log(const T& content) { src::severity_logger<severity_level> lg; BOOST_LOG_SEV(lg, logging::trivial::fatal) << content; } #endif /* Logger_hpp */
// // Logger.cpp // Test // // Created by 秦传庆 on 15/11/2. // Copyright © 2015年 秦传庆. All rights reserved. // #include "Logger.hpp" void Logger::init() { typedef sinks::synchronous_sink<sinks::text_ostream_backend> text_sink; boost::shared_ptr<text_sink> sink = boost::make_shared< text_sink >(); boost::shared_ptr<std::ostream> stream(&std::clog, boost::null_deleter()); sink->locked_backend()->add_stream(stream); auto pSink = logging::add_file_log ( keywords::file_name = "/Users/qinchuanqing/Downloads/000/sample_%N.log", keywords::rotation_size = 10 * 1024 * 1024, keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0), //keywords::format = "[%LineID%][%TimeStamp%]: %Message%" keywords::format = ( expr::stream << "[" << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << " " << expr::format_named_scope("Scope", keywords::format = "%f:%l]") << "<" << logging::trivial::severity << "> " << expr::smessage ) ); logging::core::get()->set_filter ( logging::trivial::severity >= logging::trivial::trace ); logging::core::get()->add_sink(sink); pSink->locked_backend()->auto_flush(true);//使日志实时更新 logging::core::get()->add_global_attribute("Scope", attrs::named_scope()); logging::add_common_attributes(); }
// // main.cpp // Test // // Created by 秦传庆 on 15/10/23. // Copyright © 2015年 秦传庆. All rights reserved. // #include "SpaceDistance.hpp" #include <time.h> using namespace std; int main() { Logger::init(); time_t t_start, t_end; t_start = time(NULL); SpaceDistance distance("/Users/qinchuanqing/Downloads/000/Trajectory"); double max_distance = distance.calculateDistance(); BOOST_LOG_FUNCTION(); string msg = "Max number is: "; msg.append(ConvertDataType<string>(max_distance)); info_log(msg); msg = "Total time is: "; t_end = time(NULL); msg.append(ConvertDataType<string>(difftime(t_end,t_start))); msg.append(" seconds"); BOOST_LOG_FUNCTION(); trace_log(msg); return 0; }