会员
众包
新闻
博问
闪存
赞助商
HarmonyOS
Chat2DB
所有博客
当前博客
我的博客
我的园子
账号设置
会员中心
简洁模式
...
退出登录
注册
登录
绿色冰点
为了纯粹地活着
CnBlogs
Home
New Post
Contact
Admin
Subscription
自己实现的一个寻径算法的框架,具体算法采用动态库模式,可以非常方便灵活地尝试多种寻径算法
/** * 寻径算法框架 * by lxslove * e-mail:moodlxs@163.com * 用法: * 注意:编译本框架需要加上-ldl选项 * g++ -ldl src.cpp * * 地图文件格式为不同符号的矩阵,具体什么符号代表可通行,什么符号代表不可通行,由自己决定。举个例子: * ################### * # ###### ######## * # ###### ########## * # ########## * ######## # #### * ## #### ## ###### * ### # ######### ## * ###### ##### # # ## * #### # ##### ###### * ###### ####### * ################### * 以上的例子,假设空格是可通行的,#是不可通行的。 * * 具体的算法采用插件的形式,插件(so文件)需要提供find_path函数接口,该函数的形式为: * extern "C" * int find_path(size_t start_pos, size_t end_pos, vector<char>* map_data, vector<char>* path_list) * { * return 0; //成功则返回0 * } * 编译so文件的方式例子如下: * g++ -fPIC -shared -o 1.so 1.cpp 1.h * * start_pos/end_pos为地图数据在map_data中的位置,path_list暂时没用到 * 在得到路径时,需要在find_path接口方法中修改map_data的符号,标志其为路径,具体修改为什么符号由自己决定,举个例子: * ################### * #@######@ ######## * #@######@########## * #@@@@@@@@########## * ######## # #### * ## #### ## ###### * ### # ######### ## * ###### ##### # # ## * #### # ##### ###### * ###### ####### * ################### * 以上例子中,将相应位置的符号修改为@ * 框架会直接显示地图数据,是什么符号就显示什么符号。 * */ #define DL cout #include <stdio.h> #include <string.h> #include <libgen.h> #include <dlfcn.h> #include <sys/time.h> #include <string> #include <fstream> #include <iostream> #include <vector> using namespace std; /// 插件接口 // 参数为: // 开始位置,结束位置,地图数据列表, 路径列表,暂时不用,固定为NULL typedef int (*pfunc)(size_t, size_t, vector<char>*, vector<char>*); const char* const FUNC_NAME = "find_path"; class XJFrame { private: string m_map_path; /// 地图位置 pfunc p_func; /// 插件的接口函数 vector<char> m_map_data; /// 地图数据指针 vector<size_t>* m_p_path_data; /// 路径数据指针 size_t m_map_width; /// 地图宽度 size_t m_map_heigh; /// 地图高度 void * m_p_module; /// 模块指针 struct timeval m_use_time; /// 算法耗时 public: size_t get_map_width() { return m_map_width; } size_t get_map_heigh() { return m_map_heigh; } const struct timeval* get_use_time() { return &m_use_time; } private: XJFrame(const XJFrame& rv); XJFrame& operator=(const XJFrame& rv); public: XJFrame() :m_map_width(0), m_map_heigh(0), m_p_module(NULL), m_p_path_data(NULL) { } XJFrame(const string& map_path) :m_map_path(map_path), m_map_width(0), m_map_heigh(0), m_p_module(NULL), m_p_path_data(NULL) { } ~XJFrame() { if (m_p_module) { dlclose(m_p_module); m_p_module = NULL; } if (m_p_path_data) { delete m_p_path_data; m_p_path_data = NULL; } } void set_map_path(const string & map_path) { m_map_path = map_path; } int open_module(const string & module_path) { if (module_path.empty()) { DL << "module_path not setting!\n"; return -1; } if (m_p_module) { dlclose(m_p_module); m_p_module = NULL; } void* m_p_module = dlopen(module_path.c_str(), RTLD_LAZY ); if( !m_p_module ) { DL << "can't open module: " << module_path <<", error:" << dlerror() << "\n"; return -1; } p_func = (pfunc)dlsym(m_p_module, FUNC_NAME); const char *dlsym_error = dlerror(); if (dlsym_error) { DL << "load symbol: " << FUNC_NAME << "! err: " << dlsym_error << "\n"; return -1; } return 0; } int init_map() { if (m_map_path.empty()) { DL << "map_path not setting!\n"; return -1; } m_map_data.clear(); ifstream in_file(m_map_path.c_str()); if (!in_file) { DL << "open file error:" << m_map_path << "\n"; return -1; } size_t len; char buffer[1024]; while (!in_file.eof()) { in_file.getline(buffer, sizeof(buffer)); len = strlen(buffer); if (len == 0) { break; } //根据第一次的宽度计算地图宽度 if (!m_map_width) { m_map_width = len; } else if (m_map_width != len) { DL << "map format error!0\n"; return -1; } //计算地图高度 ++m_map_heigh; //读取地图信息 for (size_t i = 0; i < len; ++i) { if ((*(buffer + i)) != ' ' && (*(buffer + i)) != '#') { DL << "map format error!2\n"; return -1; } else { m_map_data.push_back(*(buffer + i)); } } } in_file.close(); return 0; } void display_map() { if (m_map_data.empty()) { DL << "Please load map before!" << endl; return ; } DL << "Map Info: width:" << m_map_width << ", heigh:" << m_map_heigh << endl; for (int i = 0; i < m_map_data.size(); ++i) { DL << m_map_data[i]; if ((i + 1) % m_map_width == 0) { DL << "\n"; } } } int find_path(size_t start_pos, size_t end_pos) { if (m_map_data.empty()) { DL << "Please load map before!" << endl; return -1; } struct timeval tvs, tve; gettimeofday(&tvs, NULL); int ret = p_func(start_pos, end_pos, &m_map_data, NULL); gettimeofday(&tve, NULL); if (tve.tv_usec < tvs.tv_usec) { --tve.tv_sec; tve.tv_usec+=1000; } m_use_time.tv_sec = tve.tv_sec - tvs.tv_sec; m_use_time.tv_usec = tve.tv_usec - tvs.tv_usec; } }; int main(int argc, char** argv) { XJFrame xjframe; int user_select; bool is_exit = false; if (argc == 3) { xjframe.set_map_path(argv[1]); xjframe.init_map(); xjframe.open_module(argv[2]); xjframe.display_map(); } do { cout << "MENU:\nSetMap(1)\tSetModule(2)\tDisplayMap(3)\tFindPath(4)\tExit(0)" << endl; cout << "Input:" << flush; while (!(cin >> user_select)) { cout <<"Input error, retry:"<< flush; cin.clear(); cin.ignore(10000,'\n'); } string str; int ret; switch (user_select) { case 1: cout << "Your Map Path:"; cin >> str; xjframe.set_map_path(str); ret = xjframe.init_map(); if (ret != 0) { cout << "Set Map Error" << endl; } else { cout << "Set Map Success" << endl; } break; case 2: cout << "Your Module Path:"; cin >> str; ret = xjframe.open_module(str); if (ret != 0) { cout << "Set Module Error" << endl; } else { cout << "Set Module Success" << endl; } break; case 3: xjframe.display_map(); break; case 4: cout << "Enter the start position and end position,format:x y x y"; { int sx,sy,ex,ey; if (!(cin >> sx >> sy >> ex >> ey)) { cout << "Input Error!" << endl; break; } else { int start_pos = sy * xjframe.get_map_width() + sx; int end_pos = ey * xjframe.get_map_width() + ex; ret = xjframe.find_path(start_pos, end_pos); if (ret != 0) { cout << "can not find any path!" << endl; } else { cout << "path find!" << endl; xjframe.display_map(); } cout << "Use Time:" << xjframe.get_use_time()->tv_sec << " second " << xjframe.get_use_time()->tv_usec << " microsecond" << endl; } } break; case 0: is_exit = true; break; default: break; } cin.clear(); cin.ignore(10000,'\n'); }while (!is_exit); cout << "byebye" << endl; return 0; }
posted @
2011-09-09 19:22
绿色冰点
Views(
353
) Comments(
0
)
收藏
举报
刷新页面
返回顶部
公告