Skip to content

Instantly share code, notes, and snippets.

@gwaldron
Created November 12, 2020 20:09
Show Gist options
  • Save gwaldron/08726aab39801d314e1b2eb041b7088c to your computer and use it in GitHub Desktop.
Save gwaldron/08726aab39801d314e1b2eb041b7088c to your computer and use it in GitHub Desktop.
Example of memory-backed FeatureSource
#include <osgEarth/EarthManipulator>
#include <osgEarth/ExampleResources>
#include <osgEarth/FeatureSource>
#include <osgEarth/TMS>
#include <osgEarth/FeatureImageLayer>
#include <osgEarth/TerrainEngineNode>
#include <osgEarth/ViewFitter>
#include <osgViewer/Viewer>
using namespace osgEarth;
using namespace osgEarth::Util;
//! Custom feature source that stores features in memory.
//! Note: this FS will not serialize
struct MemoryFeatureSource : public FeatureSource
{
public: // FeatureSource API
//! Open the feature source
Status openImplementation() override
{
setFeatureProfile(new FeatureProfile(GeoExtent(
SpatialReference::get("wgs84"),
-180.0, -90.0, 180.0, 90.0)));
return Status::OK();
}
//! Create a cursor for iterating over the features
FeatureCursor* createFeatureCursorImplementation(
const Query& query,
ProgressCallback* progress) override
{
ScopedMutexLock lock(_mutex);
return new FeatureListCursor(_features);
}
//! Insert a new feature into the store
bool insertFeature(Feature* feature) override
{
ScopedMutexLock lock(_mutex);
feature->setFID(_fidgen++);
_features.push_back(feature);
return true;
}
bool deleteFeature(FeatureID fid) override
{
ScopedMutexLock lock(_mutex);
return false; // not implemented
}
//! Can we insert new features into this store? yes
bool isWritable() const override
{
return true;
}
private:
Mutex _mutex;
FeatureList _features;
std::atomic_int _fidgen;
};
struct App
{
MapNode* _mapNode;
FeatureSource* _features;
EarthManipulator* _manip;
Random _prng;
};
//! Event handler that adds a new feature when you press 'P'
struct AddFeature : public osgGA::GUIEventHandler
{
AddFeature(App& app) : _app(app) { }
bool handle(
const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& aa,
osg::Object*,
osg::NodeVisitor* nv)
{
if (ea.getEventType() == ea.KEYDOWN && ea.getKey() == ea.KEY_P)
{
// construct a new randomized line string:
Polygon* line = new Polygon();
line->push_back(osg::Vec3d(
-180.0 + 360.0*_app._prng.next(),
-45.0 + 90.0*_app._prng.next(),
0.0));
line->push_back(osg::Vec3d(
line->back().x() + (-10.0 + 20.0*_app._prng.next()),
line->back().y() + (-10.0 + 20.0*_app._prng.next()),
0.0));
line->push_back(osg::Vec3d(
line->back().x() + (-10.0 + 20.0*_app._prng.next()),
line->back().y() + (-10.0 + 20.0*_app._prng.next()),
0.0));
Feature* feature = new Feature(
line,
SpatialReference::get("wgs84"));
// add it to our local feature source:
_app._features->insertFeature(feature);
// tell the terrain to update itself:
std::vector<const Layer*> layers;
layers.push_back(_app._mapNode->getMap()->getLayer<FeatureImageLayer>());
_app._mapNode->getTerrainEngine()->invalidateRegion(
layers,
feature->getExtent());
// Zoom to look at our new feature
Viewpoint vp;
feature->getExtent().getCentroid(vp.focalPoint().mutable_value());
_app._manip->setViewpoint(vp, 1.0);
return true;
}
return false;
}
App _app;
};
int
main(int argc, char** argv)
{
osgEarth::initialize();
osg::ArgumentParser arguments(&argc,argv);
App app;
app._manip = new EarthManipulator(arguments);
app._manip->getSettings()->setArcViewpointTransitions(false);
osgViewer::Viewer viewer(arguments);
viewer.setCameraManipulator(app._manip);
Map* map = new Map();
TMSImageLayer* image = new TMSImageLayer();
image->setURL("http://readymap.org/readymap/tiles/1.0.0/7/");
map->addLayer(image);
// our feature store - no need to add it to the map
app._features = new MemoryFeatureSource();
// style to use for drawing the features
StyleSheet* styles = new StyleSheet();
styles->addStylesFromCSS(R"(
default {
fill: #afafaf7f;
stroke: #ff9f2f;
stroke-width: 2px;
stroke-tessellation-size: 100km;
}
)");
FeatureImageLayer* fil = new FeatureImageLayer();
fil->setFeatureSource(app._features);
fil->setStyleSheet(styles);
map->addLayer(fil);
app._mapNode = new MapNode(map);
viewer.setSceneData(app._mapNode);
viewer.addEventHandler(new AddFeature(app));
OE_NOTICE << "Press 'P' to add a line!" << std::endl;
return viewer.run();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment