A*算法在三维空间实现C++(2)——图的生成

接下来开始为生成一个图做准备。

1、根据一个顶点,构建其可行走的26个方向的剩余顶点

方法:遍历写好的directions集合,将顶点坐标与集合中的每一个方向进行计算,得到可能的26个方向的顶点坐标,保存在set集合中。

void build_directions(std::set<Point>& possible_directions, const Point& own_coords)
{
	// 根据自己的坐标生成所有26个可能的相邻坐标。
	for (const auto& vect : directions)
	{
		double d_x = std::get<0>(vect) + std::get<0>(own_coords);
		double d_y = std::get<1>(vect) + std::get<1>(own_coords);
		double d_z = std::get<2>(vect) + std::get<2>(own_coords);

		Point d_point(d_x, d_y, d_z);
		possible_directions.insert(d_point);
	}
}

2、构建一个三维空间的所有顶点

这里构建一个radius=3的立方体(3*3*3),那么直接三重循环将信息保存在graph的vertex_map中就好。

int id_count = 0;
	for (int i = 0; i < radius; i++)
	{
		for (int j = 0; j < radius; j++)
		{
			for (int k = 0; k < radius; k++)
			{
				graph.vertex_map.insert(std::make_pair(id_count, std::make_shared<GVertex>(id_count)));
				id_count++;
				// graph-vertex中id是从0开始的
			}
		}
	}

3、如何生成每个顶点与邻居节点之间的边?

生成edge比较复杂,首先第一个顶点直接生成26个方向的边即可。 那后面的顶点呢?生成的边可能会与前面的已经生成的边有重复,所以还需要进一步判断。

直接上代码;

template <typename T_Graph>
void map_nodes(T_Graph& graph, unsigned int& node_id, int& edge_ids_taken, int& node_ids_taken)
{
	// 创建包含节点node_id的所有邻接关系的邻接向量    <edge_id,neighbour_id>
	std::vector<std::pair<int, int>> adjacencies;

	// 设置所有可能的方向26个
	std::set<Point> possible_directions;

	// 如果id为0,则为第一个节点。所有其他节点都是围绕它构建的,所以已经有了坐标
	if (node_id == 0)
	{
		// 第一个节点的坐标  后面可以改
		graph.vertex_map.at(node_id).get()->coord = Point(0, 0, 0);
	}

	// 根据自己坐标求得可能的26个方向坐标
	build_directions(possible_directions, graph.vertex_map.at(node_id).get()->coord);

	// 对照邻接表,看是否已经被列为邻接点?
	for (const auto& elem : graph.adjacency_map)
	{
		bool neigh = false;
		//vector of edge_id, neighbour_id
		for (auto& ed_ne : elem.second)
		{
			//如果是邻接点
			if (ed_ne.second == node_id)
			{
				// elem是当前节点的邻居
				// adjacencies  <edge_id,neighbour_id>
				adjacencies.push_back(std::make_pair(ed_ne.first, elem.first));
				neigh = true;
			}
		}
	}



	std::set<int> adj_nodes;          //用于保存邻接点的id——集合
	std::set<int> to_add;

	// 填充adj_nodes集合
	for (const auto& elem : adjacencies)
	{
		// elem.second   =  neighbour_id
		adj_nodes.insert(elem.second);
	}

	// 对于所有邻接向量的节点  adjacencies <edge_id,neighbour_id>
	for (const auto& elem : adjacencies)
	{
		// elem.second=neighbour_id
		// graph.adjacency_map.at(elem.second) 获取到neighbour_id节点的邻接关系,边和它的邻居<edge_id,neighbour'的neigh_id>
		for (auto& ed_ne : graph.adjacency_map.at(elem.second))
		{
			
			if (possible_directions.count(graph.vertex_map.at(ed_ne.second).get()->coord))
			{
				
				// 检查是否已近被列为邻接点了?
				if (!adj_nodes.count(ed_ne.second))
				{
					
					to_add.insert(ed_ne.second);
				}
			}
		}
	}


	// 创建边
	for (const auto& id : to_add)
	{
		// adjacencies   <edge_id,neighbour_id>
		adjacencies.push_back(std::make_pair(edge_ids_taken, id));
		graph.edge_map.insert(std::make_pair(edge_ids_taken, std::make_shared<Edge>(edge_ids_taken)));
		edge_ids_taken++;
	}


	// 清除所有可能的方向
	for (const auto& coord : adjacencies)
	{
		possible_directions.erase(graph.vertex_map.at(coord.second).get()->coord);
	}

	if (!graph.vertex_map.count(node_ids_taken))
	{
		node_ids_taken = -1;
	}

	// 不存在空闲节点
	if (node_ids_taken != -1)
	{
		//对于每个可能的方向,在adj vector中添加自由节点,获取其坐标
		for (const auto& coord : possible_directions)
		{
			if (node_ids_taken != -1)
			{

				//推新边节点,增加计数器,设置节点坐标
				adjacencies.push_back(std::make_pair(edge_ids_taken, node_ids_taken));
				graph.edge_map.insert(std::make_pair(edge_ids_taken, std::make_shared<Edge>(edge_ids_taken)));


				graph.vertex_map.at(node_ids_taken).get()->coord = coord;

				node_ids_taken++;
				edge_ids_taken++;

				if (!graph.vertex_map.count(node_ids_taken))
				{
					node_ids_taken = -1;
				}
			}
		}
	}

	graph.adjacency_map.insert(std::make_pair(node_id, adjacencies));
}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值