# osgEarth构建六边形网格兵棋地图示例   在osgEarth中添加了osg::Geode,绘制蜂窝状六边形网格效果,包括墨卡托平面地图,地理坐标平面地图,三维地球等多种模式 ![alt text](assets/osgEarth六边形网格/image.png) ```c++ // 函数:创建六边形蜂窝网格线,三维地球 osg::ref_ptr createHexagonWireframe(const osgEarth::GeoExtent& extent, float radius, int rows, int cols) { osg::ref_ptr geometry = new osg::Geometry; osg::ref_ptr 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 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 stateSet = geometry->getOrCreateStateSet(); osg::ref_ptr lineWidth = new osg::LineWidth(1.0f); // 设置线宽为 1.0 stateSet->setAttributeAndModes(lineWidth, osg::StateAttribute::ON); return geometry; } // 函数:创建六边形蜂窝网格线,平面地图 osg::ref_ptr createHexagonWireframe(double startX,double startY, float radius, int rows, int cols) { osg::ref_ptr geometry = new osg::Geometry; osg::ref_ptr 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 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 stateSet = geometry->getOrCreateStateSet(); osg::ref_ptr 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 * ...