164 lines
5.2 KiB
C++
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();
|
|
} |