一个算法思路 都进来看看 谢谢

请叫我卷福 2011-08-09 02:38:57
现在情况描述如下:
我有一张地图(类似如下图,实际情况不一样),从A到B点,有各种不同的路径可以走,比如指令"H1-F1"(可以先沿H1走,再沿F1走)、"R1-F2-R3"(可以先沿R1走,再沿F2走,再沿R3走)等等。。。

一上路径都是不规则的,就是说不一定是直线,有可能是半圆、斜线等等
现在我程序中我一个小车,我要完成的功能是:小车在A点,我下指令,让它沿着指令走到B点,界面我用MFC已经做得差不多了,就是 我想问一下,怎么个思路实现这个算法,涉及地图坐标是一定要的吧... 不会判断什么时候该换方向 希望各位大神指教 给点思路 谢谢 在线等

如下图:


谢谢各位!
...全文
843 53 打赏 收藏 转发到动态 举报
写回复
用AI写文章
53 条回复
切换为时间正序
请发表友善的回复…
发表回复
Frog1228 2011-08-19
  • 打赏
  • 举报
回复
[Quote=引用 52 楼 qq274840476 的回复:]
记得上一个坐标A(a,b),当前坐标B(C,D)
坐标表中挑选出来的坐标C(e,f)。通过A、B算出角度,B、C算出角度,应该就能知道怎么歪弯了·
[/Quote]
跟我说的一样。
可惜楼主弃楼了。。。
youandme111 2011-08-18
  • 打赏
  • 举报
回复
就是用到数据结构里面的最有路径问题吧,不过我现在已经不记得了
qq274840476 2011-08-18
  • 打赏
  • 举报
回复
记得上一个坐标A(a,b),当前坐标B(C,D)
坐标表中挑选出来的坐标C(e,f)。通过A、B算出角度,B、C算出角度,应该就能知道怎么歪弯了·
biegaoshuwoya 2011-08-16
  • 打赏
  • 举报
回复
弄个坐标系,弄函数。。。 其实我是打酱油的,,,
wjlsmail 2011-08-16
  • 打赏
  • 举报
回复
关注一下
Frog1228 2011-08-13
  • 打赏
  • 举报
回复
[Quote=引用 48 楼 wulj_0614 的回复:]
有一行写错了,重新发下


C/C++ code

#define MAX_VERTEX 20

// 顶点
struct Vertex
{
std::string sName;
float fX, fY;
};

// 边基类
class Edge
{
public:
std::string sName; // 边名字
……
[/Quote]
楼主都弃楼了,你激情好澎湃。。。
horicon 2011-08-12
  • 打赏
  • 举报
回复
表示不懂
赵4老师 2011-08-12
  • 打赏
  • 举报
回复
wulj_0614 2011-08-12
  • 打赏
  • 举报
回复
有一行写错了,重新发下


#define MAX_VERTEX 20

// 顶点
struct Vertex
{
std::string sName;
float fX, fY;
};

// 边基类
class Edge
{
public:
std::string sName; // 边名字
Vertex* pStart; // 起点
Vertex* pEnd; // 终点编号

// 本边的长度
virtual float lenth() const = 0;
// 根据离起点的距离取得点坐标
virtual void getPoint(float &fX, float &fY, float fLen) const = 0;
};

// 直线边
class LineEdge : public Edge
{
public:
void length() const
{
float fDX = pEnd->fX - pStart->fX;
float fDY = pEnd->fY - pStart->fY;
return sqrtf(fDX * fDX + fDY * fDY);
}
void getPoint(float &fX, float &fY, float fLen) const
{
float fDX = vEnd.fX - vStart.fX;
float fDY = vEnd.fY - vStart.fY;
float fT = fLen / sqrtf(fDX * fDX + fDY * fDY);

if (fT < 0.0f)
{
fX = vStart.x;
fY = vStart.y;
}
else if (fT > 1.0f)
{
fX = vEnd.x;
fY = vEnd.y;
}
else
{
fX = vStart.x * (1 - fT) + vEnd.x * fT;
fY = vStart.y * (1 - fT) + vEnd.x * fT;
}
}
};

// 弧度边
class ArcEdge : public Edge
{
public:
// 圆心坐标
float fX, fY;

void length() const
{
// TODO:...
}
void getPoint(float &fX, float &fY, float fLen) const
{
// TODO:...
}
}

// 有向图
class Graph
{
public:
Vertex Vertexes[MAX_VERTEX];
int nVertexNum;
std::vector<Edge*> Edges;

Edge* getEdgeByIndex(int nIndex);
int getEdgeIndexByName(const std::string &sName);
};

// 画行走路径
class PathDrawer
{
private:
DWORD nStartTime; // 开始时间
std::vector<int> Path; // 边索引路径
int nPathIndex; // 当前路径边
float fPreEdgeLen; // 已经走过的边的长度和
float fSpeed; // 移动速度
Graph *pGraph; // 图

public:
// sPath是以空格分开的边序列
bool setPath(const std::string& sPath)
{
// TODO:生成Path,并检查路径是否合法
}

// 每帧调用它渲染
void render()
{
if (Path.empty() || nPathIndex >= Path.size())
return;

// 走到的点
float fX, fY;

// 这一帧要走的距离
DWORD nDTime = timeGetTime() - nStartTime;
float fLen = fSpeed * nDTime / 1000;

Edge* pEdge = pGraph->getEdgeByIndex(Path[nPathIndex]);
float fEdgeLen = pEdge->length();

// 如果走过改变了,则到下一条边去
while (fPreEdgeLen + fEdgeLen < fLen)
{
// 路径加1
++nPathIndex;
fPreEdgeLen += fEdgeLen;

// 到达终点了
if (nPathIndex >= Path.size())
break;

// 取下一条路径
pEdge = pGraph->getEdgeByIndex(Path[nPathIndex]);
fEdgeLen = pEdge->lenth();
}

// 计算走到的点
if (nPathIndex >= Path.size())
{
fX = pEdge->pEnd->fX;
fY = pEdge->pEnd->fY;
}
else
{
pEdge->getPoint(fX, fY, fLen - fPreEdgeLen);
}

// TODO:画点(fX, fY)
}
};
wulj_0614 2011-08-12
  • 打赏
  • 举报
回复
楼主要的应该是这个吧!
部分代码没写,楼主自己去补充下吧!

#define MAX_VERTEX 20

// 顶点
struct Vertex
{
std::string sName;
float fX, fY;
};

// 边基类
class Edge
{
public:
std::string sName; // 边名字
Vertex* pStart; // 起点
Vertex* pEnd; // 终点编号

// 本边的长度
virtual float lenth() const = 0;
// 根据离起点的距离取得点坐标
virtual void getPoint(float &fX, float &fY, float fLen) const = 0;
};

// 直线边
class LineEdge : public Edge
{
public:
void length() const
{
float fDX = pEnd->fX - pStart->fX;
float fDY = pEnd->fY - pStart->fY;
return sqrtf(fDX * fDX + fDY * fDY);
}
void getPoint(float &fX, float &fY, float fLen) const
{
float fDX = vEnd.fX - vStart.fX;
float fDY = vEnd.fY - vStart.fY;
float fT = fLen / sqrtf(fDX * fDX + fDY * fDY);

if (fT < 0.0f)
{
fX = vStart.x;
fY = vStart.y;
}
else if (fT > 1.0f)
{
fX = vEnd.x;
fY = vEnd.y;
}
else
{
fX = vStart.x * (1 - fT) + vEnd.x * fT;
fY = vStart.y * (1 - fT) + vEnd.x * fT;
}
}
};

// 弧度边
class ArcEdge : public Edge
{
public:
// 圆心坐标
float fX, fY;

void length() const
{
// TODO:...
}
void getPoint(float &fX, float &fY, float fLen) const
{
// TODO:...
}
}

// 有向图
class Graph
{
public:
Vertex Vertexes[MAX_VERTEX];
int nVertexNum;
std::vector<Edge*> Edges;

Edge* getEdgeByIndex(int nIndex);
int getEdgeIndexByName(const std::string &sName);
};

// 画行走路径
class PathDrawer
{
private:
DWORD nStartTime; // 开始时间
std::vector<int> Path; // 边索引路径
int nPathIndex; // 当前路径边
float fPreEdgeLen; // 已经走过的边的长度和
float fSpeed; // 移动速度
Graph *pGraph; // 图

public:
// sPath是以空格分开的边序列
bool setPath(const std::string& sPath)
{
// TODO:生成Path,并检查路径是否合法
}

// 每帧调用它渲染
void render()
{
if (Path.empty() || nPathIndex >= Path.size())
return;

// 走到的点
float fX, fY;

// 这一帧要走的距离
DWORD nDTime = timeGetTime() - nStartTime;
float fLen = fSpeed * nDTime / 1000;

Edge* pEdge = pGraph->getEdgeByIndex(Path[nPathIndex]);
float fEdgeLen = pEdge->length();

// 如果走过改变了,则到下一条边去
while (fPreEdgeLen + fEdgeLen < fLen)
{
// 路径加1
++nPathIndex;
fPreEdgeLen += fEdgeLen;

// 到达终点了
if (nPathIndex >= Path.size())
break;

// 取下一条路径
pEdge = pGraph->getEdgeByIndex(Path[nPathIndex]);
fEdgeLen = pEdge->lenth();
}

// 计算走到的点
if (nPathIndex >= Path.size())
{
fX = pEdge->pEnd->fX;
fY = pEdge->pEnd->fY;
}
else
{
float fT = (fLen - fPreEdgeLen) / fEdgeLen;
fX = pEdge->pStart->fX * (1.0f - fT) + pEdge->pEnd->fX;
fY = pEdge->pStart->fY * (1.0f - fT) + pEdge->pEnd->fY;
}

// TODO:画点(fX, fY)
}
};
daniel2go 2011-08-11
  • 打赏
  • 举报
回复
不是最短路径
Alexander 2011-08-11
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 dayong98 的回复:]

引用 11 楼 xiaozhi_5638 的回复:

引用 9 楼 pathuang68 的回复:
1. 先把所有交点的坐标算出来,放到一个列表里面。
2. 当车走到交点的位置,就可以判断是否该考虑换方向了。

还是您明白了我的意思

路径不是直线 有弯曲的线 怎么判断方向? 而且要沿着(覆盖)路径走

同意9楼观点。坐标点以及可以从这个点转向的路径,比如走到A点时可以……
[/Quote]
我的思路:
不要把交点存列表,存成这样一个链表结构(最好是双向链表,方便逆向检索)
路径结点(可以保存路径方程等相关信息)->交点1->交点2->……
交点结点里可存放坐标、指向相交的路径结点的指针。
交点存放顺序:可以用你喜欢的任何方式,如:
一次曲线用:左->右(竖直时上->下),或者上->下(水平时左->右)
二次曲线用以顺时针或逆时针为正向。
……

例如:选择路径为R1->R2->R3
当小车到达R1与R2交点Si时,判断R2与R3的交点在Si的正方向还是反方向,至于x向与y向的步长值嘛,就由行进方向与R2的方程决定了。
xuzysun 2011-08-11
  • 打赏
  • 举报
回复
看看!!
w495771636 2011-08-11
  • 打赏
  • 举报
回复
分配路径不合理。
dfasri 2011-08-11
  • 打赏
  • 举报
回复
每条路线, 总是会跟其他路线相连接, 不连接的话, 路也走不通.
记录下当前路线与其他路线的交汇坐标, 并且标识每个交点延线的一个方向上能够达哪些路线, 另一个方向上能够到达哪些路线, 就可以知道要转哪边了吧.
不过交点的链表得要手工完成.

属于F2的交点集会有

H1-F2 H2-F2 R1-F2 R2-F2 R3-F2, H3-F2

其中 R3-F2 的向左行会有 H1-F2 H2-F2 R1-F2 R2-F2 这些交点, 向右行会有 H3-F2

本来图是能够解决路线的问题, 但由于加入了手工指定的方式, 不采用结构的方式, 就必须对目的地进行划分. 即用图计算每一个小目的地的路线, 例如 R1,F2,R3的话, 则先用图计算R1-F2交点为目的地的路线, 再计算到F2-R3的路线, 最后计算最终目的地的路线, 即每次到达交点, 就得要计算下一个交点怎样走, 然后行走, 这样的速度很慢, 我想也不是你想要的, 所以建议使用树形结构. 每一条路线都有一个, 直接查询比用图来算会比较快.
AnYidan 2011-08-11
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 xiaozhi_5638 的回复:]
谢谢楼上 关注此贴的人们!!!

奥巴马保佑你们
[/Quote]

谁来保佑奥巴马?
zscedu 2011-08-11
  • 打赏
  • 举报
回复
我来看看,帮你顶一下
  • 打赏
  • 举报
回复
嵌入式的那个小车车比赛
Frog1228 2011-08-11
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 mjjackey 的回复:]
两条直线的斜率相差的角度就是小车的转向角,如果是半圆的,你也是取半圆上的点,还是按两点构成一直线,如果要走得精确点,点就分得细点,但是完全按圆形走是不可能的。
[/Quote]
如果要确定x,y方向的行进值,比如定一个y值,由y*tagAlpha得到x,Alpha就是转向角。
楼上的很多给出由图或树找出路径,就是确定这一点该朝哪一点走,其实楼主的意思是,遇到这些拐点后,如何控制小车的转向和行进。
貌似楼主消失了。。。
coder_s 2011-08-10
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 wzx110113627 的回复:]

这个问题是典型的图算法嘛
你把各个定点做成一个个节点,
各个线段就是连接线,然后以你A点位跟,把这个图拆成书,找到B点之后你退推来的路径就是你要的路径。
具体的算法内容,你去查相关的资料吧。在这边简单了写,你也未必能看懂。
不知道我说的是不是你要的。

其实我觉得,如果路径是你自己给定的话,你把各个连接点的坐标都记录出来。然后小车按路径一个一个走就是了。应该没什么难的
[/Quote]
+1
加载更多回复(33)

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧