Files
test_maplibre/module/test_osg_earth/main.cpp
T
2026-07-20 16:05:32 +08:00

164 lines
5.2 KiB
C++

#include <cstddef>
#include <iostream>
#include <string>
#include <vector>
#include <osg/ArgumentParser>
#include <osg/Notify>
#include <osgDB/FileUtils>
#include <osgDB/Registry>
#include <osgViewer/Viewer>
#include <osgEarth/Controls>
#include <osgEarth/EarthManipulator>
#include <osgEarth/GLUtils>
#include <osgEarth/MapNode>
#include <osgEarth/Viewpoint>
#include <osgEarth/XYZ>
#ifdef _WIN32
#include <windows.h>
#endif
namespace ui = osgEarth::Util::Controls;
struct Tile_Source {
std::string name;
std::string url;
};
class Tile_Source_Controller {
public:
explicit Tile_Source_Controller(osgEarth::Map* map) : map_(map) {}
void add_source(Tile_Source source, bool visible) {
osg::ref_ptr<osgEarth::XYZImageLayer> layer = new osgEarth::XYZImageLayer();
layer->setName(source.name);
layer->setURL(source.url);
layer->setProfile(osgEarth::Profile::create(osgEarth::Profile::SPHERICAL_MERCATOR));
layer->setVisible(visible);
map_->addLayer(layer.get());
sources_.emplace_back(std::move(source));
layers_.emplace_back(std::move(layer));
}
void select(std::size_t index) {
for (std::size_t i = 0; i < layers_.size(); ++i) {
layers_[i]->setVisible(i == index);
}
status_->setText(std::string("Current: ") + sources_[index].name);
}
void set_status(ui::LabelControl* status) {
status_ = status;
}
[[nodiscard]] std::size_t size() const {
return sources_.size();
}
[[nodiscard]] const std::string& name(std::size_t index) const {
return sources_[index].name;
}
private:
osgEarth::Map* map_;
std::vector<Tile_Source> sources_;
std::vector<osg::ref_ptr<osgEarth::XYZImageLayer>> layers_;
ui::LabelControl* status_;
};
class Select_Tile_Source_Handler : public ui::ControlEventHandler {
public:
Select_Tile_Source_Handler(Tile_Source_Controller& controller, std::size_t index)
: controller_(controller), index_(index) {}
void onClick(ui::Control*) {
controller_.select(index_);
}
private:
Tile_Source_Controller& controller_;
std::size_t index_;
};
ui::Control* create_tile_source_panel(Tile_Source_Controller& controller) {
auto* grid = new ui::Grid();
grid->setBackColor(0.0f, 0.0f, 0.0f, 0.72f);
grid->setPadding(10.0f);
grid->setChildSpacing(6.0f);
grid->setAbsorbEvents(true);
unsigned int row = 0;
grid->setControl(0, row++, new ui::LabelControl("Tile source"));
for (std::size_t i = 0; i < controller.size(); ++i) {
auto* button = grid->setControl(
0,
row++,
new ui::ButtonControl(
controller.name(i),
new Select_Tile_Source_Handler(controller, i)
)
);
button->setHorizFill(true, 220.0f);
}
auto* status = grid->setControl(
0,
row,
new ui::LabelControl("Current: OpenStreetMap")
);
controller.set_status(status);
return grid;
}
int main(int argc, char** argv) {
#ifdef _WIN32
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
#endif
const std::string install_root =
"D:/ae/cached_external_library/vs2019_Debug_osg_earth/install";
osgDB::FilePathList plugin_paths{
install_root + "/osgearth/bin/osgPlugins-3.6.5",
install_root + "/openscenegraph/bin/osgPlugins-3.6.5"
};
auto* registry = osgDB::Registry::instance();
registry->setLibraryFilePathList(plugin_paths);
osg::setNotifyLevel(osg::NOTICE);
if (registry->getReaderWriterForExtension("png") == nullptr) {
std::cerr << "无法加载 OSG PNG 插件,请检查 osgdb_pngd.dll 和它依赖的 DLL\n";
return 1;
}
osgEarth::initialize();
osg::ArgumentParser args(&argc, argv);
osg::ref_ptr<osgEarth::Map> map = new osgEarth::Map();
Tile_Source_Controller tile_sources(map.get());
tile_sources.add_source(
{
"OpenStreetMap",
"https://tile.openstreetmap.org/{z}/{x}/{y}.png"
},
true
);
tile_sources.add_source(
{
"OpenTopoMap",
"https://[abc].tile.opentopomap.org/{z}/{x}/{y}.png"
},
false
);
tile_sources.add_source(
{
"Esri World Imagery",
"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
},
false
);
osg::ref_ptr<osgEarth::MapNode> map_node = new osgEarth::MapNode(map.get());
osgViewer::Viewer viewer(args);
viewer.setUpViewInWindow(100, 100, 1280, 720);
viewer.setRealizeOperation(new osgEarth::GL3RealizeOperation());
viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
viewer.setSceneData(map_node.get());
ui::ControlCanvas::getOrCreate(&viewer)->addControl(
create_tile_source_panel(tile_sources)
);
osg::ref_ptr<osgEarth::EarthManipulator> manipulator =
new osgEarth::EarthManipulator(args);
viewer.setCameraManipulator(manipulator.get());
manipulator->setViewpoint(
osgEarth::Viewpoint(
"Beijing",
116.4074,
39.9042,
0.0,
0.0,
-90.0,
1500000.0
),
0.0
);
return viewer.run();
}