OSGEARTH开发三维地球
背景介绍
由于先前搞了一个qgis的二维地图,现在项目组提出新的需求,需要二维三维地图进行联动。经过前期的调研,发现qgis好像并不具备三维地图展示的能力,于是搜索到osg, osgearth ,经过的几天的编译折腾,环境搞定了。我们的项目主要涉及,点,线,面绘制,shp文件,tif文件加载。飞机模型演示等,具体需求相对简单。
经过几天的摸索,初步完成了三维地图的加载,点,线,面的绘制工作。并且将osgearth与Qt进行了结合。下面来看看代码。
Qt 与 osgearth示例代码
main.cpp文件
#include "MWidget.h"
#include
#include
int usage(const std::string& msg, osg::ArgumentParser& args)
{
OE_NOTICE << msg << std::endl << std::endl;
OE_NOTICE << "USAGE: " << args[0] << " file.earth" << std::endl;
return -1;
}
int main(int argc, char** argv)
{
qDebug() << "argv[1]:" << argv[1] ;
osg::ArgumentParser args(&argc, argv);
if (args.find("--help") >= 0)
return usage("Help", args);
osg::ref_ptr<osg::Node> node = osgDB::readNodeFiles(args);
if (!node.valid())
return usage("Can't load a scene!", args);
QApplication q(argc, argv);
MWidget m(args, node.get());
m.show();
return q.exec();
}
MWidget.h 文件
#pragma once
#include
#include "ui_MWidget.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
class MWidget : public QWidget
{
Q_OBJECT
public:
MWidget(QWidget *parent = Q_NULLPTR);
MWidget( osg::ArgumentParser& args, osg::Node* scene, QWidget *parent = Q_NULLPTR);
void paintEvent(QPaintEvent* e);
public slots:
void addView();
public:
QTimer _timer;
osgViewer::CompositeViewer _viewer;
osg::ref_ptr<osg::Node> _scene;
osg::ref_ptr<osg::Node> node;
private:
Ui::MWidget ui;
};
MWidget.cpp 文件
#include "MWidget.h"
using namespace osgEarth;
using namespace osgEarth::Util;
using namespace osgEarth::QtGui;
using namespace osgEarth::Annotation;
using namespace osgEarth::Features;
MWidget::MWidget(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
}
MWidget::MWidget( osg::ArgumentParser& args, osg::Node* scene, QWidget *parent)
: QWidget(parent), _viewer(args), _scene(scene)
{
ui.setupUi(this);
node = scene;
_viewer.setThreadingModel(_viewer.SingleThreaded);
connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
_timer.start(20);
connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(addView()));
addView();
}
void MWidget::paintEvent(QPaintEvent* e)
{
if (_viewer.getRunFrameScheme() == osgViewer::ViewerBase::CONTINUOUS ||
_viewer.checkNeedToDoFrame())
{
_viewer.frame();
}
}
void MWidget::addView()
{
osgViewer::View* view = new osgViewer::View();
QWidget* viewWidget = new osgEarth::QtGui::ViewWidget(view);
osg::Group* root = new osg::Group();
MapNode* mapNode = MapNode::findMapNode(node);
if (!mapNode)
;
osg::Group* annoGroup = new osg::Group();
MapNode::get(node)->addChild(annoGroup);
osg::Group* labelGroup = new osg::Group();
annoGroup->addChild(labelGroup);
osg::Group* editGroup = new osg::Group();
MapNode::get(node)->addChild(editGroup);
Style labelStyle;
labelStyle.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_CENTER;
labelStyle.getOrCreate<TextSymbol>()->fill()->color() = Color::Yellow;
const SpatialReference* geoSRS = mapNode->getMapSRS()->getGeographicSRS();
{
Style pm;
pm.getOrCreate<IconSymbol>()->url()->setLiteral("../data/placemark32.png");
pm.getOrCreate<IconSymbol>()->declutter() = true;
pm.getOrCreate<TextSymbol>()->halo() = Color("#5f5f5f");
labelGroup->addChild(new PlaceNode(GeoPoint(geoSRS, -74.00, 40.71), "New York", pm));
labelGroup->addChild(new PlaceNode(GeoPoint(geoSRS, -77.04, 38.85), "Washington, DC", pm));
labelGroup->addChild(new PlaceNode(GeoPoint(geoSRS, -118.40, 33.93), "Los Angeles", pm));
labelGroup->addChild(new PlaceNode(GeoPoint(geoSRS, -71.03, 42.37), "Boston", pm));
labelGroup->addChild(new PlaceNode(GeoPoint(geoSRS, -157.93, 21.35), "Honolulu", pm));
labelGroup->addChild(new PlaceNode(GeoPoint(geoSRS, 139.75, 35.68), "Tokyo", pm));
labelGroup->addChild(new PlaceNode(GeoPoint(geoSRS, -90.25, 29.98), "New Orleans", pm));
labelGroup->addChild(new PlaceNode(GeoPoint(geoSRS, -80.28, 25.82), "Miami", pm));
labelGroup->addChild(new PlaceNode(GeoPoint(geoSRS, -117.17, 32.72), "San Diego", pm));
osg::LOD* lod = new osg::LOD();
lod->addChild(new PlaceNode(GeoPoint(geoSRS, 14.68, 50.0), "Prague", pm), 0.0, 2e6);
labelGroup->addChild(lod);
labelGroup->addChild(new PlaceNode(GeoPoint(geoSRS, -87.65, 41.90, 1000, ALTMODE_ABSOLUTE), "Chicago", pm));
}
{
struct C : public osg::NodeCallback {
void operator()(osg::Node* n, osg::NodeVisitor* nv) {
static int i = 0;
i++;
if (i % 100 < 50)
traverse(n, nv);
}
};
Geometry* geom = new osgEarth::Symbology::Polygon();
geom->push_back(osg::Vec3d(0, 40, 0));
geom->push_back(osg::Vec3d(-60, 40, 0));
geom->push_back(osg::Vec3d(-60, 60, 0));
geom->push_back(osg::Vec3d(0, 60, 0));
Feature* feature = new Feature(geom, geoSRS);
feature->geoInterp() = GEOINTERP_RHUMB_LINE;
Style geomStyle;
geomStyle.getOrCreate<LineSymbol>()->stroke()->color() = Color::Red;
geomStyle.getOrCreate<LineSymbol>()->stroke()->width() = 5.0f;
geomStyle.getOrCreate<LineSymbol>()->tessellationSize() = 75000;
geomStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
geomStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_GPU;
FeatureNode* fnode = new FeatureNode(feature, geomStyle);
fnode->addCullCallback(new C());
annoGroup->addChild(fnode);
LabelNode* label = new LabelNode("Rhumb line polygon", labelStyle);
label->setPosition(GeoPoint(geoSRS, -30, 50));
labelGroup->addChild(label);
}
{
Geometry* geom = new osgEarth::Symbology::Polygon();
geom->push_back(-160., -30.);
geom->push_back(150., -20.);
geom->push_back(160., -45.);
geom->push_back(-150., -40.);
Style geomStyle;
Feature* feature = new Feature(geom, geoSRS);
feature->geoInterp() = GEOINTERP_RHUMB_LINE;
geomStyle.getOrCreate<LineSymbol>()->stroke()->color() = Color::Lime;
geomStyle.getOrCreate<LineSymbol>()->stroke()->width() = 3.0f;
geomStyle.getOrCreate<LineSymbol>()->tessellationSize() = 75000;
geomStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
geomStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_GPU;
FeatureNode* gnode = new FeatureNode(feature, geomStyle);
annoGroup->addChild(gnode);
LabelNode* label = new LabelNode("Antimeridian polygon", labelStyle);
label->setPosition(GeoPoint(geoSRS, -175, -35));
labelGroup->addChild(label);
}
FeatureNode* pathNode = 0;
{
Geometry* path = new LineString();
path->push_back(osg::Vec3d(-74, 40.714, 0));
path->push_back(osg::Vec3d(139.75, 35.68, 0));
Feature* pathFeature = new Feature(path, geoSRS);
pathFeature->geoInterp() = GEOINTERP_GREAT_CIRCLE;
Style pathStyle;
pathStyle.getOrCreate<LineSymbol>()->stroke()->color() = Color::White;
pathStyle.getOrCreate<LineSymbol>()->stroke()->width() = 1.0f;
pathStyle.getOrCreate<LineSymbol>()->stroke()->smooth() = true;
pathStyle.getOrCreate<LineSymbol>()->tessellationSize() = 75000;
pathStyle.getOrCreate<PointSymbol>()->size() = 8;
pathStyle.getOrCreate<PointSymbol>()->fill()->color() = Color::Red;
pathStyle.getOrCreate<PointSymbol>()->smooth() = true;
pathStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
pathStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_GPU;
pathStyle.getOrCreate<RenderSymbol>()->depthOffset()->enabled() = true;
pathNode = new FeatureNode(pathFeature, pathStyle);
annoGroup->addChild(pathNode);
LabelNode* label = new LabelNode("Great circle path", labelStyle);
label->setPosition(GeoPoint(geoSRS, -170, 61.2));
labelGroup->addChild(label);
}
{
Style circleStyle;
circleStyle.getOrCreate<PolygonSymbol>()->fill()->color() = Color(Color::Cyan, 0.5);
circleStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
circleStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_DRAPE;
CircleNode* circle = new CircleNode();
circle->set(
GeoPoint(geoSRS, -90.25, 29.98, 1000., ALTMODE_RELATIVE),
Distance(300, Units::KILOMETERS),
circleStyle,
Angle(-45.0, Units::DEGREES),
Angle(45.0, Units::DEGREES),
true);
annoGroup->addChild(circle);
editGroup->addChild(new CircleNodeEditor(circle));
}
{
Style circleStyle;
circleStyle.getOrCreate<PolygonSymbol>()->fill()->color() = Color(Color::Red, 0.5);
circleStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
circleStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_DRAPE;
CircleNode* circle = new CircleNode();
circle->set(
GeoPoint(geoSRS, -90.25, 29.98, 1000., ALTMODE_RELATIVE),
Distance(300, Units::KILOMETERS),
circleStyle,
Angle(45.0, Units::DEGREES),
Angle(360.0 - 45.0, Units::DEGREES),
true);
annoGroup->addChild(circle);
editGroup->addChild(new CircleNodeEditor(circle));
}
{
Style ellipseStyle;
ellipseStyle.getOrCreate<PolygonSymbol>()->fill()->color() = Color(Color::Orange, 0.75);
ellipseStyle.getOrCreate<ExtrusionSymbol>()->height() = 250000.0;
EllipseNode* ellipse = new EllipseNode();
ellipse->set(
GeoPoint(geoSRS, -80.28, 25.82, 0.0, ALTMODE_RELATIVE),
Distance(250, Units::MILES),
Distance(100, Units::MILES),
Angle(0, Units::DEGREES),
ellipseStyle,
Angle(45.0, Units::DEGREES),
Angle(360.0 - 45.0, Units::DEGREES),
true);
annoGroup->addChild(ellipse);
editGroup->addChild(new EllipseNodeEditor(ellipse));
}
{
Style ellipseStyle;
ellipseStyle.getOrCreate<PolygonSymbol>()->fill()->color() = Color(Color::Blue, 0.75);
ellipseStyle.getOrCreate<ExtrusionSymbol>()->height() = 250000.0;
EllipseNode* ellipse = new EllipseNode();
ellipse->set(
GeoPoint(geoSRS, -80.28, 25.82, 0.0, ALTMODE_RELATIVE),
Distance(250, Units::MILES),
Distance(100, Units::MILES),
Angle(0, Units::DEGREES),
ellipseStyle,
Angle(-40.0, Units::DEGREES),
Angle(40.0, Units::DEGREES),
true);
annoGroup->addChild(ellipse);
editGroup->addChild(new EllipseNodeEditor(ellipse));
}
{
Style rectStyle;
rectStyle.getOrCreate<ExtrusionSymbol>()->height() = 1250000.0;
rectStyle.getOrCreate<PolygonSymbol>()->fill()->color() = Color(Color::Green, 0.5);
rectStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
rectStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_DRAPE;
RectangleNode* rect = new RectangleNode(
GeoPoint(geoSRS, -117.172, 32.721),
Distance(300, Units::KILOMETERS),
Distance(600, Units::KILOMETERS),
rectStyle);
annoGroup->addChild(rect);
editGroup->addChild(new RectangleNodeEditor(rect));
}
{
Geometry* utah = new osgEarth::Symbology::Polygon();
utah->push_back(-114.052, 37.0);
utah->push_back(-109.054, 37.0);
utah->push_back(-109.054, 41.0);
utah->push_back(-111.040, 41.0);
utah->push_back(-111.080, 42.059);
utah->push_back(-114.080, 42.024);
Style utahStyle;
utahStyle.getOrCreate<ExtrusionSymbol>()->height() = 1250000.0;
utahStyle.getOrCreate<PolygonSymbol>()->fill()->color() = Color(Color::Red, 0.8);
Feature* utahFeature = new Feature(utah, geoSRS);
FeatureNode* featureNode = new FeatureNode(utahFeature, utahStyle);
annoGroup->addChild(featureNode);
}
{
ImageOverlay* imageOverlay = 0L;
osg::ref_ptr<osg::Image> image = osgDB::readRefImageFile("../data/USFLAG.TGA");
if (image.valid())
{
imageOverlay = new ImageOverlay(mapNode, image.get());
imageOverlay->setBounds(Bounds(-100.0, 35.0, -90.0, 40.0));
annoGroup->addChild(imageOverlay);
editGroup->addChild(new ImageOverlayEditor(imageOverlay));
}
}
{
Style style;
style.getOrCreate<ModelSymbol>()->autoScale() = true;
style.getOrCreate<ModelSymbol>()->url()->setLiteral("../data/red_flag.osg.50.scale");
ModelNode* modelNode = new ModelNode(mapNode, style);
modelNode->setPosition(GeoPoint(geoSRS, -100, 52));
annoGroup->addChild(modelNode);
}
QDialog* win = new QDialog(this);
win->setModal(false);
win->setLayout(new QHBoxLayout());
win->layout()->addWidget(viewWidget);
int x = osgEarth::Random().next(1024);
int y = osgEarth::Random().next(768);
qDebug() << "x:" << x << " y:" << y << endl;
win->setGeometry(x, y, 640, 480);
win->show();
view->setCameraManipulator(new osgEarth::Util::EarthManipulator);
view->setSceneData(_scene.get());
view->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, false);
_viewer.addView(view);
}
效果展示
点击addview 按钮不断的产生新图片.
![osgearth开发三维地球_第1张图片](http://img.e-com-net.com/image/info8/115615c554be4531afe93619c404d358.jpg)
![osgearth开发三维地球_第2张图片](http://img.e-com-net.com/image/info8/64d1d8b593e848d29b7a5c270f0fe7d6.jpg)