# osgEarth构建六边形网格兵棋地图示例

　　在osgEarth中添加了osg::Geode，绘制蜂窝状六边形网格效果，包括墨卡托平面地图，地理坐标平面地图，三维地球等多种模式
![alt text](assets/osgEarth六边形网格/image.png)
```cpp
// 函数：创建六边形蜂窝网格线，三维地球
osg::ref_ptr<osg::Geometry> createHexagonWireframe(const osgEarth::GeoExtent& extent, float radius, int rows, int cols) {
	osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;

	osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;

	auto fromSRS = osgEarth::SpatialReference::get("wgs84");
	auto srs = extent.getSRS();

	// 计算每个六边形中心点的地理坐标
	float height = std::sqrt(3.0f) * radius;
	float lonDelta = radius;// extent.width() / cols;
	float latDelta = radius;// extent.height() / rows;
	for (int row = 0; row < rows; ++row) {
		for (int col = 0; col < cols; ++col) {

			float lonDelta = col * 1.5f * radius;
			float latDelta = row * height;
			if (col % 2 == 1)
				latDelta += height / 2.0f;

			float lon = 108.0 + lonDelta;
			float lat = 35.0 + latDelta;
			osg::Vec3d centerGeo(lon, lat, 3000.0);

			// 计算六边形的顶点
			for (int i = 0; i < 6; ++i) 
			{
				float angle = osg::PI * 2.0f * float(i) / 6.0f;
				float x = radius * std::cos(angle);
				float y = radius * std::sin(angle);
				osg::Vec3d vertexXYZ;
				osgEarth::GeoPoint pppp(fromSRS, osg::Vec3d(lon + x, lat + y, 1.0));
				pppp.transformInPlace(srs);
				pppp.toWorld(vertexXYZ);
				//vertices->push_back(centerXYZ + vertexXYZ - centerGeo);
				vertices->push_back(vertexXYZ);
			}
		}
	}

	geometry->setVertexArray(vertices);

	osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt(GL_LINES);
	int numHexagons = rows * cols;

	for (int i = 0; i < numHexagons; ++i) {
		int offset = i * 6;
		for (int j = 0; j < 6; ++j) {
			indices->push_back(offset + j);
			indices->push_back(offset + (j + 1) % 6);
		}
	}

	geometry->addPrimitiveSet(indices);

	// 启用 VBO
	geometry->setUseVertexBufferObjects(true);

	// 设置线宽
	osg::ref_ptr<osg::StateSet> stateSet = geometry->getOrCreateStateSet();
	osg::ref_ptr<osg::LineWidth> lineWidth = new osg::LineWidth(1.0f); // 设置线宽为 1.0
	stateSet->setAttributeAndModes(lineWidth, osg::StateAttribute::ON);

	return geometry;
}


// 函数：创建六边形蜂窝网格线,平面地图
osg::ref_ptr<osg::Geometry> createHexagonWireframe(double startX,double startY, float radius, int rows, int cols) {
	osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;

	osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;


	// 计算每个六边形中心点的地理坐标
	float height = std::sqrt(3.0f) * radius;
	for (int row = 0; row < rows; ++row) 
	{
		for (int col = 0; col < cols; ++col) 
		{
			float xDelta = col * 1.5f * radius;
			float yDelta = row * height;
			if (col % 2 == 1)
				yDelta += height / 2.0f;

			float lon = startX + xDelta;
			float lat = startY + yDelta;

			// 计算六边形的顶点
			for (int i = 0; i < 6; ++i)
			{
				float angle = osg::PI * 2.0f * float(i) / 6.0f;
				float x = radius * std::cos(angle);
				float y = radius * std::sin(angle);
				//vertices->push_back(centerXYZ + vertexXYZ - centerGeo);
				vertices->push_back(osg::Vec3d(lon + x, lat + y, 1.0));
			}
		}
	}

	geometry->setVertexArray(vertices);

	osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt(GL_LINES);
	int numHexagons = rows * cols;

	for (int i = 0; i < numHexagons; ++i) {
		int offset = i * 6;
		for (int j = 0; j < 6; ++j) {
			indices->push_back(offset + j);
			indices->push_back(offset + (j + 1) % 6);
		}
	}

	geometry->addPrimitiveSet(indices);

	// 启用 VBO
	geometry->setUseVertexBufferObjects(true);

	// 设置线宽
	osg::ref_ptr<osg::StateSet> stateSet = geometry->getOrCreateStateSet();
	osg::ref_ptr<osg::LineWidth> lineWidth = new osg::LineWidth(1.0f); // 设置线宽为 1.0
	stateSet->setAttributeAndModes(lineWidth, osg::StateAttribute::ON);

	return geometry;
}


int main(int argc, char* argv[])
{
	auto ddMap = osgDB::readNodeFile("E:/GISData/Imagery/2dmap.earth");

	auto mapNode = osgEarth::MapNode::findMapNode(ddMap);

	osgEarth::GeoPoint start(osgEarth::SpatialReference::get("wgs84"), 108.0, 35.0);
	start.transformInPlace(mapNode->getMapSRS());

	auto hexagon222 = createHexagonWireframe(start.x(), start.y()
		, 500, 100, 100);

	hexagon222->getOrCreateStateSet()->setAttribute(new osg::Depth(osg::Depth::ALWAYS, 0.0, 1.0, false), osg::StateAttribute::ON);
	osgEarth::GLUtils::setLighting(hexagon222->getOrCreateStateSet(), osg::StateAttribute::OFF);

	mapNode->addChild(hexagon222);

	auto m = new osgEarth::EarthManipulator;

	osgViewer::Viewer viewer;
	viewer.setSceneData(ddMap);
	
	viewer.setCameraManipulator(m);
	viewer.getCamera()->addCullCallback(new osgEarth::AutoClipPlaneCullCallback(mapNode));

	viewer.realize();


	m->setViewpoint(osgEarth::Viewpoint("", 108, 35, 0.0, 0.0, -89.9, 100000));

	return viewer.run();
}
```

## 附件
![2dmap.earth](assets/osgEarth六边形网格/2dmap.earth)

## 性能问题
 * 考虑使用instanced drawing
 * 使用kd-tree
 * ...