#include "FindPath.h"
static FindPath g_FindPath;
POpenFile *g_pOPenFile = NULL;
PCloseFile *g_pCloseFile = NULL;
PReadFile *g_pReadFile = NULL;
PGetFileSize *g_pGetFileSize = NULL;
FILE * g_OpenFile(const char *psFileName,const char *psMode);
bool g_CloseFile(FILE *pFile);
size_t g_ReadFile(FILE *fp, void *buffer,size_t size);
size_t g_GetFileSize(const char *psFileName);
Log_System g_log;
extern bool GetScenePathInfo(const char * inifilename, const char * scene_res, std::string & pathfile, std::string & tgafile, SceneRect & rect);
extern bool SceneFindPath(const char * inifilename, const char * begin_sceneid,float sx,float sz,float sy, const char * end_sceneid,float dx,float dz,float dy,std::vector<SCENEPATHITEM> &pathsecene);
FILE * g_OpenFile(const char *psFileName,const char *psMode)
{
if (g_pOPenFile == NULL)
{
return fopen(psFileName,psMode);
}
else
{
return (FILE *)(*g_pOPenFile)(psFileName,psMode);
}
}
bool g_CloseFile(FILE *pFile)
{
if (g_pCloseFile == NULL)
{
return fclose(pFile) == 0;
}
else
{
return (*g_pCloseFile)(pFile);
}
}
size_t g_ReadFile(FILE *fp, void *buffer,size_t size)
{
if (g_pReadFile == NULL)
{
return (int)fread(buffer, 1, size, fp);
}
else
{
return (*g_pReadFile)(fp, buffer,size);
}
}
size_t g_GetFileSize(const char *psFileName)
{
if (g_pGetFileSize == NULL)
{
FILE * fp = fopen(psFileName, "rb");
::fseek(fp, 0, SEEK_END);
long size = ::ftell(fp);
::fseek(fp, 0, SEEK_SET);
::fclose(fp);
return size;
}
else
{
return (*g_pGetFileSize)(psFileName);
}
}
FindPath::FindPath()
{
g_log.OpenLog();
}
FindPath::~FindPath()
{
ReleaseAllPath();
}
bool FindPath::SetFileFunc(const char *FunName,void *FunPointer)
{
if (strcmp(FunName,"OpenFile") == 0)
{
g_pOPenFile = (POpenFile*)FunPointer;
return true;
}
if (strcmp(FunName,"CloseFile") == 0)
{
g_pCloseFile = (PCloseFile*)FunPointer;
return true;
}
if (strcmp(FunName,"ReadFile") == 0)
{
g_pReadFile = (PReadFile*)FunPointer;
return true;
}
if (strcmp(FunName,"GetFileSize") == 0)
{
g_pGetFileSize = (PGetFileSize*)FunPointer;
return true;
}
return false;
}
void FindPath::InitFindPath(const char * path)
{
m_strPath = path;
m_IniFileName = path;
m_IniFileName += "path_finding.ini";
}
//获得指定场景的路点总数
int FindPath::GetPathPointCount(const char * scene_res)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return 0;
CSceneMap * pSceneMap = it->second;
if(pSceneMap == NULL)
return 0;
return pSceneMap->GetPathPointCount();
}
//获得指定场景的指定区域的路点索引列表
int FindPath::GetPathPointInZone(const char * scene_res, float x, float z, float radius, int point_lst[], int max_count)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return false;
CSceneMap * pSceneMap = it->second;
if(pSceneMap == NULL)
return false;
return pSceneMap->GetPathPointInZone(x, z, radius, point_lst, max_count);
}
//获得指定场景的指定路点的信息
PATHPOINT * FindPath::GetPathPointInfo(const char * scene_res, int index)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return NULL;
CSceneMap * pSceneMap = it->second;
if(pSceneMap == NULL)
return NULL;
return pSceneMap->GetPathPointInfo(index);
}
//添加路点
int FindPath::AddPathPoint(const char * scene_res, float x, float y, float z)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return -1;
CSceneMap * pSceneMap = it->second;
if(pSceneMap == NULL)
return -1;
return pSceneMap->AddPathPoint(x, y, z);
}
//修改路点位置
bool FindPath::SetPathPointPos(const char * scene_res, int index, float x, float y, float z)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return -1;
CSceneMap * pSceneMap = it->second;
if(pSceneMap == NULL)
return -1;
return pSceneMap->SetPathPointPos(index, x, y, z);
}
//删除路点
void FindPath::RemovePathPoint(const char * scene_res, int index)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return;
CSceneMap * pSceneMap = it->second;
if(pSceneMap == NULL)
return;
pSceneMap->RemovePathPoint(index);
}
//添加连通关系
bool FindPath::AddLink(const char * scene_res, int index, int link_index)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return false;
CSceneMap * pSceneMap = it->second;
if(pSceneMap == NULL)
return false;
return pSceneMap->AddLink(index, link_index);
}
//删除连通关系
void FindPath::RemoveLink(const char * scene_res, int index, int link_index)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return;
CSceneMap * pSceneMap = it->second;
if(pSceneMap == NULL)
return;
pSceneMap->RemoveLink(index, link_index);
}
//数据是否已加载
bool FindPath::IsLoaded(const char * scene_res)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return false;
return true;
}
bool FindPath::NewPath(const char * scene_res, ISceneMapProcess * pSceneMapProcess)
{
if (IsLoaded(scene_res))
{
//数据已加载
return false;
}
CSceneMap * pSceneMap = new CSceneMap(scene_res, pSceneMapProcess);
m_mapSceneMaps.insert(std::make_pair(scene_res, pSceneMap));
return true;
}
bool FindPath::LoadPath(const char * scene_res, ISceneMapProcess * pSceneMapProcess)
{
g_log.wirtetime();
if (IsLoaded(scene_res))
{
//数据已加载
return false;
}
//加载地图
CSceneMap * pSceneMap = new CSceneMap(scene_res, pSceneMapProcess);
std::string full_path = m_strPath + scene_res + ".path";
if(!pSceneMap->LoadPath(full_path.c_str()))
{
delete pSceneMap;
return false;
}
m_mapSceneMaps.insert(std::make_pair(scene_res, pSceneMap));
return true;
}
bool FindPath::SavePath(const char * scene_res)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return false;
CSceneMap * pSceneMap = it->second;
if(pSceneMap == NULL)
return false;
std::string full_path = m_strPath + scene_res + ".path";
return pSceneMap->SavePath(full_path.c_str());
}
void FindPath::ReleasePath(const char * scene_res)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
//数据未加载
return;
CSceneMap * pSceneMap = it->second;
if(pSceneMap != NULL)
AW_SAFE_DELETE(pSceneMap);
m_mapSceneMaps.erase(it);
g_log.wirtetime();
}
void FindPath::ReleaseAllPath()
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.begin();
for (; it != m_mapSceneMaps.end(); ++it)
AW_SAFE_DELETE (it->second );
m_mapSceneMaps.clear();
}
int FindPath::PointFindPath(const char * scene_res, float xBegin, float zBegin, float yBegin,
float xEnd, float zEnd, float yEnd,
float x[], float y[], int maxcount, bool optimize)
{
if (maxcount < 2)
return 0;
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return 0;
CSceneMap * pSceneMap = it->second;
if(pSceneMap == NULL)
return 0;
if (((xBegin - xEnd) * (xBegin - xEnd) + (zBegin - zEnd) * (zBegin - zEnd)) <= DIST_VALVA*DIST_VALVA)
{
if(pSceneMap->TryLine(xBegin, yBegin, zBegin,xEnd, yEnd, zEnd))
{
//如果两点距离比较近并且中间没有被阻挡,则直接走向目标点
x[0] = xBegin;
y[0] = zBegin;
x[1] = xEnd;
y[1] = zEnd;
return 2;
}
}
//创建地图信息
CPathUser pathUser(pSceneMap);
//开始寻路
if (!pathUser.FindPath(xBegin, yBegin, zBegin,xEnd, yEnd, zEnd))
return 0;
int count = pathUser.GetPathPointCount();
if (count > maxcount)
count = maxcount;
//把点写入用户的容器里
if (!optimize)
{
//不优化处理
for (int i = 0 ; i < count; i++)
{
float xtemp, ytemp, ztemp;
pathUser.GetPathPoint(i, xtemp, ytemp, ztemp);
x[i] = xtemp;
y[i] = ztemp;
}
}
else
{
//优化处理
//当前处理的点
int cur_proc_index = -1;
//当前压入的点
int last_push_index = -1;
while(true)
{
cur_proc_index++;
if (cur_proc_index >= count)
break;
//取当前正在处理的点的坐标
float xtemp, ytemp, ztemp;
pathUser.GetPathPoint(cur_proc_index, xtemp, ytemp, ztemp);
//是否可以丢弃最后一个被压入的点
bool b_canreplace = false;
if (last_push_index > 0)
{
//取上一个点
float xtemp1 = x[last_push_index - 1];
float ytemp1 = ytemp;
float ztemp1 = y[last_push_index - 1];
//与当前正在处理的点是否直接连通
if (TryLine(scene_res, xtemp1, ytemp1, ztemp1, xtemp, ytemp, ztemp))
b_canreplace = true;
}
if (!b_canreplace)
//最后一个被压入的点不可以丢弃,添加到新的位置
last_push_index++;
x[last_push_index] = xtemp;
y[last_push_index] = ztemp;
}
//有效的路点数量
count = last_push_index + 1;
}
return count;
}
int FindPath::SceneFindPath(const char * begin_scene_res, float xBegin, float zBegin, float yBegin,
const char * end_scene_res, float xEnd, float zEnd, float yEnd,
SCENEPATHITEM scenepath[], int maxcount)
{
if (maxcount < 2)
return 0;
std::vector<SCENEPATHITEM> pathsecene;
if(!::SceneFindPath(m_IniFileName.c_str(), begin_scene_res,xBegin,zBegin,yBegin,end_scene_res,xEnd,zEnd,yEnd,pathsecene))
return 0;
if (pathsecene.size() == 0)
{
scenepath[0].sceneid = begin_scene_res;
scenepath[0].xBegin = xBegin;
scenepath[0].yBegin = zBegin;
scenepath[0].xEnd = xEnd;
scenepath[0].yEnd = zEnd;
return (int)pathsecene.size() + 1;
}
//将路点 存为输出模式(场景号,起始点,结束点)
int count = (int)pathsecene.size();
if (count > maxcount - 1)
count = maxcount - 1;
for (int i = 0 ; i <= count ; i++)
{
if (i == 0)
{
scenepath[i].sceneid = begin_scene_res;
scenepath[i].xBegin = xBegin;
scenepath[i].yBegin = zBegin;
scenepath[i].xEnd = pathsecene[i].xBegin;
scenepath[i].yEnd = pathsecene[i].yBegin;
continue;
}
if (i == pathsecene.size())
{
scenepath[i].sceneid = end_scene_res;
scenepath[i].xBegin = pathsecene[i - 1].xEnd;
scenepath[i].yBegin = pathsecene[i - 1].yEnd;
scenepath[i].xEnd = xEnd;
scenepath[i].yEnd = zEnd;
break;
}
scenepath[i].sceneid = pathsecene[i - 1].sceneid;
scenepath[i].xBegin = pathsecene[i - 1].xEnd;
scenepath[i].yBegin = pathsecene[i - 1].yEnd;
scenepath[i].xEnd = pathsecene[i].xBegin;
scenepath[i].yEnd = pathsecene[i].yBegin;
}
return count + 1;
}
bool FindPath::TryPoint(const char * scene_res, float x, float y, float z)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return false;
CSceneMap * pSceneMap = it->second;
if (pSceneMap == NULL)
return false;
return pSceneMap->TryPoint(x, y, z);
}
bool FindPath::TryLine(const char * scene_res, float xb, float yb, float zb, float xe, float ye, float ze)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return false;
CSceneMap *pSceneMap = it->second;
if (pSceneMap == NULL)
return false;
return pSceneMap->TryLine(xb, yb, zb, xe, ye, ze);
}
CSceneMap* FindPath::FindSceneMap(const char * scene_res)
{
std::map<std::string, CSceneMap*>::iterator it = m_mapSceneMaps.find(scene_res);
if (it == m_mapSceneMaps.end())
return NULL;
return (*it).second;
}
IFindPath* IFindPath::GetPointer()
{
return &g_FindPath;
};