void test_ImageOverlay::split_ShouldReturnExpectedResults_data() { QList<ImageOverlay> overlays = ImageOverlayTestHelper::createImageOverlays(); QList< QList<ImageOverlay> > overlaysSubOverlays = ImageOverlayTestHelper::createSubOverlays(); QTest::addColumn<ImageOverlay>("overlay"); QTest::addColumn< QList<ImageOverlay> >("subOverlays"); ImageOverlay overlay; QTest::newRow("invalid overlay") << overlay << QList<ImageOverlay>(); overlay.setRows(128); overlay.setColumns(128); overlay.setData(new unsigned char[128 * 128]); memset(overlay.getData(), 0, 128 * 128 * sizeof(unsigned char)); QTest::newRow("empty overlay") << overlay << QList<ImageOverlay>(); QTest::newRow("overlay #1") << overlays[0] << overlaysSubOverlays[0]; // overlays[1] és per quan no optimitzem per potències de 2 //QTest::newRow("overlay #2") << overlays[1] << overlaysSubOverlays[1]; QTest::newRow("overlay #3") << overlays[2] << overlaysSubOverlays[2]; QTest::newRow("overlay #4") << overlays[3] << overlaysSubOverlays[3]; // overlays[4] és per quan sí optimitzem per potències de 2 QTest::newRow("overlay #5") << overlays[4] << overlaysSubOverlays[4]; }
void test_ImageOverlay::createSubOverlay_ShouldReturnInvalidOverlay_data() { QTest::addColumn<ImageOverlay>("overlay"); QTest::addColumn<QRect>("region"); ImageOverlay overlay; overlay.setRows(5); overlay.setColumns(5); QTest::newRow("invalid overlay, region not inside") << overlay << QRect(1, 2, 7, 3); QTest::newRow("invalid overlay, region inside") << overlay << QRect(1, 1, 1, 1); overlay.setData(new unsigned char[1]); QTest::newRow("valid overlay, region not inside") << overlay << QRect(1, 2, 7, 3); }
void test_ImageOverlay::fromGDCMOverlay_ReturnsExpectedValues_data() { QTest::addColumn<gdcm::Overlay>("gdcmOverlay"); QTest::addColumn<ImageOverlay>("imageOverlay"); gdcm::Overlay emptyGDCMOverlay; ImageOverlay imageOverlayLikeEmptyGDCMOverlay; imageOverlayLikeEmptyGDCMOverlay.setOrigin(0, 0); QTest::newRow("empty gdcm overlay") << emptyGDCMOverlay << imageOverlayLikeEmptyGDCMOverlay; int rows = 5; int columns = 7; short origin[2] = { 22, -12 }; const char *gdcmBuffer = new char[rows * columns]; gdcm::Overlay overlayWithData; overlayWithData.SetColumns(columns); overlayWithData.SetRows(rows); overlayWithData.SetOrigin(origin); overlayWithData.SetOverlay(gdcmBuffer, rows * columns); size_t bufferSize = overlayWithData.GetUnpackBufferLength(); unsigned char *imageOverlayBuffer = new unsigned char[bufferSize]; overlayWithData.GetUnpackBuffer(reinterpret_cast<char*>(imageOverlayBuffer), bufferSize); ImageOverlay imageOverlay; imageOverlay.setRows(rows); imageOverlay.setColumns(columns); imageOverlay.setOrigin(origin[0], origin[1]); imageOverlay.setData(imageOverlayBuffer); QTest::newRow("gdcm overlay with data") << overlayWithData << imageOverlay; }
void LibraryMenuItem::init(QSharedPointer<Library> &library) { _library = library; _closeButton = NULL; QString fontFamily = themeManager->getValueAsFontFamilyName(QT_NT("ui.message.font.family"),QT_NT("")); int fontSize = themeManager->getValueAsInt(QT_NT("ui.message.font.size"), 14); TextOverlay* text = new TextOverlay(_library->getName()); text->getStyle().setAlpha(1.0f); text->setFont(FontDescription(fontFamily, fontSize)); text->getStyle().setBackgroundColor(ColorVal(0, 0, 0, 0)); text->getStyle().setPadding(LeftRightEdges, 0.0f); text->getStyle().setPadding(TopBottomEdges, 0.0f); float height = (float)text->getTextBuffer().getActualSize().height(); ImageOverlay* icon = new ImageOverlay(_library->getIconTextureKey()); icon->getStyle().setScaledDimensions(Vec3(height, height, 0.0f)); this->addItem(icon); this->addItem(text); }
void test_ImageOverlay::ImageOverlay_InitializesClassAsExpected() { ImageOverlay overlay; QCOMPARE(overlay.getRows(), 0); QCOMPARE(overlay.getColumns(), 0); QCOMPARE(overlay.getXOrigin(), 1); QCOMPARE(overlay.getYOrigin(), 1); unsigned char *nullUCharPointer = 0; QCOMPARE(overlay.getData(), nullUCharPointer); }
int main(int argc, char** argv) { osg::ArgumentParser arguments(&argc,argv); osg::DisplaySettings::instance()->setMinimumNumStencilBits( 8 ); std::vector< std::string > imageFiles; std::vector< Bounds > imageBounds; //Read in the image files std::string filename; Bounds bounds; while (arguments.read("--image", filename, bounds.xMin(), bounds.yMin(), bounds.xMax(), bounds.yMax())) { imageFiles.push_back( filename ); imageBounds.push_back( bounds ); } if (imageFiles.empty()) { imageFiles.push_back("../data/osgearth.gif"); imageBounds.push_back( Bounds(-100, 30, -90, 40) ); } bool moveVert = arguments.read("--vert"); // load the .earth file from the command line. osg::Node* earthNode = osgDB::readNodeFiles( arguments ); if (!earthNode) return usage( "Unable to load earth model." ); osgViewer::Viewer viewer(arguments); EarthManipulator* manip = new EarthManipulator(); viewer.setCameraManipulator( manip ); osg::Group* root = new osg::Group(); root->addChild( earthNode ); //Create the control panel root->addChild( createControlPanel(&viewer) ); viewer.setSceneData( root ); osgEarth::MapNode* mapNode = osgEarth::MapNode::findMapNode( earthNode ); if ( mapNode ) { for (unsigned int i = 0; i < imageFiles.size(); i++) { std::string imageFile = imageFiles[i]; //Read the image file and play it if it's a movie osg::Image* image = osgDB::readImageFile(imageFile); if (image) { osg::ImageStream* is = dynamic_cast<osg::ImageStream*>(image); if (is) { is->play(); } } //Create a new ImageOverlay and set it's bounds //ImageOverlay* overlay = new ImageOverlay(mapNode->getMap()->getProfile()->getSRS()->getEllipsoid(), image); ImageOverlay* overlay = new ImageOverlay(mapNode); overlay->setImage( image ); overlay->setBounds(imageBounds[i]); root->addChild( overlay ); //Create a new ImageOverlayEditor and set it's node mask to 0 to hide it initially #if OSG_MIN_VERSION_REQUIRED(2,9,6) osg::Node* editor = new ImageOverlayEditor( overlay); #else //Just make an empty group for pre-2.9.6 osg::Node* editor = new osg::Group; #endif editor->setNodeMask( 0 ); root->addChild( editor ); // Add an image preview ImageControl* imageCon = new ImageControl( image ); imageCon->setSize( 64, 64 ); imageCon->setVertAlign( Control::ALIGN_CENTER ); s_layerBox->setControl( 0, i, imageCon ); //Add some controls CheckBoxControl* enabled = new CheckBoxControl( true ); enabled->addEventHandler( new EnabledHandler(overlay) ); enabled->setVertAlign( Control::ALIGN_CENTER ); s_layerBox->setControl( 1, i, enabled ); //The overlay name LabelControl* name = new LabelControl( osgDB::getSimpleFileName( imageFile) ); name->setVertAlign( Control::ALIGN_CENTER ); s_layerBox->setControl( 2, i, name ); // an opacity slider HSliderControl* opacity = new HSliderControl( 0.0f, 1.0f, overlay->getAlpha() ); opacity->setWidth( 125 ); opacity->setHeight( 12 ); opacity->setVertAlign( Control::ALIGN_CENTER ); opacity->addEventHandler( new OpacityHandler(overlay) ); s_layerBox->setControl( 3, i, opacity ); // Add a text label: LabelControl* edit = new LabelControl( "Edit" ); edit->setVertAlign( Control::ALIGN_CENTER ); edit->addEventHandler(new EditHandler(overlay, &viewer, editor)); s_layerBox->setControl(4, i, edit ); } } // osgEarth benefits from pre-compilation of GL objects in the pager. In newer versions of // OSG, this activates OSG's IncrementalCompileOpeartion in order to avoid frame breaks. viewer.getDatabasePager()->setDoPreCompile( true ); // add some stock OSG handlers: viewer.addEventHandler(new osgViewer::StatsHandler()); viewer.addEventHandler(new osgViewer::WindowSizeHandler()); viewer.addEventHandler(new osgViewer::LODScaleHandler()); viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())); viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage())); return viewer.run(); }
void test_ImageOverlay::isValid_ReturnsExpectedValue_data() { QTest::addColumn<ImageOverlay>("imageOverlay"); QTest::addColumn<bool>("expectedValue"); ImageOverlay imageOverlay; imageOverlay.setRows(0); imageOverlay.setColumns(0); imageOverlay.setData(0); QTest::newRow("no rows, no columns, no data") << imageOverlay << false; imageOverlay.setRows(0); imageOverlay.setColumns(0); imageOverlay.setData(new unsigned char[1]); QTest::newRow("no rows, no columns, data") << imageOverlay << false; imageOverlay.setRows(0); imageOverlay.setColumns(1); imageOverlay.setData(0); QTest::newRow("no rows, columns, no data") << imageOverlay << false; imageOverlay.setRows(0); imageOverlay.setColumns(2); imageOverlay.setData(new unsigned char[1]); QTest::newRow("no rows, columns, data") << imageOverlay << false; imageOverlay.setRows(3); imageOverlay.setColumns(0); imageOverlay.setData(0); QTest::newRow("rows, no columns, no data") << imageOverlay << false; imageOverlay.setRows(4); imageOverlay.setColumns(0); imageOverlay.setData(new unsigned char[1]); QTest::newRow("rows, no columns, data") << imageOverlay << false; imageOverlay.setRows(5); imageOverlay.setColumns(6); imageOverlay.setData(0); QTest::newRow("rows, columns, no data") << imageOverlay << false; imageOverlay.setRows(7); imageOverlay.setColumns(8); imageOverlay.setData(new unsigned char[1]); QTest::newRow("rows, columns, data") << imageOverlay << true; }
void test_ImageOverlay::mergeOverlays_ReturnsExpectedImageOverlay_data() { QTest::addColumn<QList<ImageOverlay> >("overlaysList"); QTest::addColumn<ImageOverlay>("mergedOverlay"); QTest::addColumn<bool>("mergeWasSuccessful"); QList<ImageOverlay> overlaysList; QTest::newRow("Empty List") << overlaysList << ImageOverlay() << true; ImageOverlay overlay1; overlay1.setColumns(512); overlay1.setRows(512); overlay1.setOrigin(1, 1); unsigned char *data1 = new unsigned char[512 * 512]; memset(data1, 0, sizeof(unsigned char) * 512 * 512); memset(data1, 255, sizeof(unsigned char) * 512); overlay1.setData(data1); overlaysList.clear(); overlaysList << overlay1; QTest::newRow("Single element list") << overlaysList << overlay1 << true; overlaysList.clear(); overlaysList << overlay1 << overlay1; QTest::newRow("2 elements, same data") << overlaysList << overlay1 << true; ImageOverlay overlay2 = overlay1; unsigned char *data2 = new unsigned char[512 * 512]; memset(data2, 0, sizeof(unsigned char) * 512 * 512); memset(data2 + sizeof(unsigned char) * 512, 255, sizeof(unsigned char) * 512); overlay2.setData(data2); ImageOverlay mergedOverlay; mergedOverlay.setColumns(512); mergedOverlay.setRows(512); mergedOverlay.setOrigin(1, 1); unsigned char *mergedData1 = new unsigned char[512 * 512]; memset(mergedData1, 0, sizeof(unsigned char) * 512 * 512); memset(mergedData1, 255, sizeof(unsigned char) * 1024); mergedOverlay.setData(mergedData1); overlaysList.clear(); overlaysList << overlay1 << overlay2; QTest::newRow("2 overlays, same origin, same cols x rows, different data") << overlaysList << mergedOverlay << true; ImageOverlay overlay3; overlay3.setColumns(512); overlay3.setRows(512); overlay3.setOrigin(-10, 5); unsigned char *data3 = new unsigned char[512 * 512]; memset(data3, 0, sizeof(unsigned char) * 512 * 512); memset(data3, 255, sizeof(unsigned char) * 512); overlay3.setData(data3); ImageOverlay mergedOverlay1_3; mergedOverlay1_3.setColumns(512 + 11); mergedOverlay1_3.setRows(512 + 4); mergedOverlay1_3.setOrigin(-10, 1); int dataLength = mergedOverlay1_3.getColumns() * mergedOverlay1_3.getRows(); unsigned char *mergedData1_3 = new unsigned char[dataLength]; memset(mergedData1_3, 0, sizeof(unsigned char) * dataLength); memset(mergedData1_3 + sizeof(unsigned char) * 11, 255, sizeof(unsigned char) * 512); memset(mergedData1_3 + sizeof(unsigned char) * mergedOverlay1_3.getColumns() * 4, 255, sizeof(unsigned char) * 512); mergedOverlay1_3.setData(mergedData1_3); overlaysList.clear(); overlaysList << overlay1 << overlay3; QTest::newRow("2 overlays, different origin, same cols x rows") << overlaysList << mergedOverlay1_3 << true; ImageOverlay overlay4; overlay4.setColumns(10); overlay4.setRows(10); overlay4.setOrigin(1, 1); unsigned char *data4 = new unsigned char[10 * 10]; memset(data4, 0, sizeof(unsigned char) * 100); memset(data4, 255, sizeof(unsigned char) * 10); overlay4.setData(data4); ImageOverlay overlay5; overlay5.setColumns(11); overlay5.setRows(11); overlay5.setOrigin(1, 1); unsigned char *data5 = new unsigned char[11 * 11]; memset(data5, 0, sizeof(unsigned char) * 121); memset(data5 + sizeof(unsigned char) * 11 * 10, 255, sizeof(unsigned char) * 11); overlay5.setData(data5); ImageOverlay mergedOverlay4_5; mergedOverlay4_5.setColumns(11); mergedOverlay4_5.setRows(11); mergedOverlay4_5.setOrigin(1, 1); unsigned char *mergedData4_5 = new unsigned char[11 * 11]; memset(mergedData4_5, 0, sizeof(unsigned char) * 121); memset(mergedData4_5, 255, sizeof(unsigned char) * 10); memset(mergedData4_5 + sizeof(unsigned char) * 11 * 10, 255, sizeof(unsigned char) * 11); mergedOverlay4_5.setData(mergedData4_5); overlaysList.clear(); overlaysList << overlay4 << overlay5; QTest::newRow("2 overlays, same origin, different cols x rows") << overlaysList << mergedOverlay4_5 << true; ImageOverlay overlay6; overlay6.setColumns(8); overlay6.setRows(6); overlay6.setOrigin(2, -10); unsigned char *data6 = new unsigned char[6 * 8]; memset(data6, 0, sizeof(unsigned char) * 48); data6[0] = 255; data6[13] = 255; data6[42] = 255; overlay6.setData(data6); ImageOverlay overlay7; overlay7.setColumns(3); overlay7.setRows(20); overlay7.setOrigin(-6, -7); unsigned char *data7 = new unsigned char[3 * 20]; memset(data7, 0, sizeof(unsigned char) * 60); data7[0] = 255; data7[1] = 255; data7[31] = 255; data7[59] = 255; overlay7.setData(data7); ImageOverlay mergedOverlay6_7; mergedOverlay6_7.setColumns(16); mergedOverlay6_7.setRows(23); mergedOverlay6_7.setOrigin(-6, -10); unsigned char *mergedData6_7 = new unsigned char[23 * 16]; memset(mergedData6_7, 0, sizeof(unsigned char) * 23 * 16); mergedData6_7[8] = 255; mergedData6_7[29] = 255; mergedData6_7[48] = 255; mergedData6_7[49] = 255; mergedData6_7[90] = 255; mergedData6_7[209] = 255; mergedData6_7[354] = 255; mergedOverlay6_7.setData(mergedData6_7); overlaysList.clear(); overlaysList << overlay6 << overlay7; QTest::newRow("2 overlays, different origin, different cols x rows") << overlaysList << mergedOverlay6_7 << true; ImageOverlay nullRowsOverlay; nullRowsOverlay.setColumns(512); nullRowsOverlay.setRows(0); nullRowsOverlay.setOrigin(3, 25); overlaysList.clear(); overlaysList << overlay1 << nullRowsOverlay; QTest::newRow("2 overlays, one invalid (no rows)") << overlaysList << overlay1 << true; ImageOverlay nullColumnsOverlay; nullColumnsOverlay.setColumns(0); nullColumnsOverlay.setRows(128); nullColumnsOverlay.setOrigin(2, 5); overlaysList.clear(); overlaysList << overlay1 << nullColumnsOverlay; QTest::newRow("2 overlays, one invalid (no columns)") << overlaysList << overlay1 << true; ImageOverlay nullDataOverlay; nullDataOverlay.setColumns(128); nullDataOverlay.setRows(128); nullDataOverlay.setOrigin(2, 5); nullDataOverlay.setData(0); overlaysList.clear(); overlaysList << overlay1 << nullDataOverlay; QTest::newRow("2 overlays, one invalid (no data)") << overlaysList << overlay1 << true; overlaysList.clear(); overlaysList << ImageOverlay() << ImageOverlay(); QTest::newRow("2 empty overlays") << overlaysList << ImageOverlay() << true; overlaysList.clear(); overlaysList << nullRowsOverlay; QTest::newRow("1 invalid overlay (no rows)") << overlaysList << ImageOverlay() << true; overlaysList.clear(); overlaysList << nullColumnsOverlay; QTest::newRow("1 invalid overlay (no columns)") << overlaysList << ImageOverlay() << true; overlaysList.clear(); overlaysList << nullDataOverlay; QTest::newRow("1 invalid overlay (no data)") << overlaysList << ImageOverlay() << true; overlaysList.clear(); overlaysList << nullColumnsOverlay << nullRowsOverlay << nullDataOverlay; QTest::newRow("3 invalid overlays (no rows, no columns, no data)") << overlaysList << ImageOverlay() << true; }
void KML_GroundOverlay::build( const Config& conf, KMLContext& cx ) { // the URL of the overlay image std::string href = conf.child("icon").value("href"); if ( href.empty() ) { OE_WARN << LC << "GroundOverlay missing required Icon element" << std::endl; return; } ImageOverlay* im = 0L; // the extent of the overlay image const Config& llb = conf.child("latlonbox"); if ( !llb.empty() ) { double north = llb.value<double>("north", 0.0); double south = llb.value<double>("south", 0.0); double east = llb.value<double>("east", 0.0); double west = llb.value<double>("west", 0.0); Angular rotation( -llb.value<double>("rotation", 0.0), Units::DEGREES ); osg::ref_ptr<osg::Image> image = URI(href, conf.referrer()).readImage().getImage(); if ( !image.valid() ) { OE_WARN << LC << "GroundOverlay failed to read image from " << href << std::endl; return; } im = new ImageOverlay( cx._mapNode, image.get() ); im->setBoundsAndRotation( Bounds(west, south, east, north), rotation ); cx._groupStack.top()->addChild( im ); } else if ( conf.hasChild("gx:latlonquad") ) { const Config& llq = conf.child("gx:latlonquad"); KML_Geometry g; Style style; g.buildChild( llq, cx, style ); if ( g._geom.valid() && g._geom->size() >= 4 ) { osg::ref_ptr<osg::Image> image = URI(href, conf.referrer()).readImage().getImage(); if ( !image.valid() ) { OE_WARN << LC << "GroundOverlay failed to read image from " << href << std::endl; return; } const Geometry& p = *(g._geom.get()); im = new ImageOverlay( cx._mapNode, image.get() ); im->setCorners( osg::Vec2d( p[0].x(), p[0].y() ), osg::Vec2d( p[1].x(), p[1].y() ), osg::Vec2d( p[3].x(), p[3].y() ), osg::Vec2d( p[2].x(), p[2].y() ) ); cx._groupStack.top()->addChild( im ); } } else { OE_WARN << LC << "GroundOverlay missing required LatLonBox/gx:LatLonQuad element" << std::endl; return; } // superclass build always called last KML_Overlay::build( conf, cx, im ); }
int main(int argc, char** argv) { osg::Group* root = new osg::Group(); // try to load an earth file. osg::ArgumentParser arguments(&argc,argv); osgViewer::Viewer viewer(arguments); viewer.setCameraManipulator( new EarthManipulator() ); // load an earth file and parse demo arguments osg::Node* node = MapNodeHelper().load(arguments, &viewer); if ( !node ) return usage(argv); root->addChild( node ); // find the map node that we loaded. MapNode* mapNode = MapNode::findMapNode(node); if ( !mapNode ) return usage(argv); // Group to hold all our annotation elements. osg::Group* annoGroup = new osg::Group(); root->addChild( annoGroup ); //A group for all the editors osg::Group* editorGroup = new osg::Group; root->addChild( editorGroup ); editorGroup->setNodeMask( 0 ); HBox* box = ControlCanvas::getOrCreate(&viewer)->addControl( new HBox() ); box->setChildSpacing( 5 ); //Add a toggle button to toggle editing CheckBoxControl* editCheckbox = new CheckBoxControl( false ); editCheckbox->addEventHandler( new ToggleNodeHandler( editorGroup ) ); box->addControl( editCheckbox ); LabelControl* labelControl = new LabelControl( "Edit Annotations" ); labelControl->setFontSize( 24.0f ); box->addControl( labelControl ); // Make a group for 2D items, and activate the decluttering engine. Decluttering // will migitate overlap between elements that occupy the same screen real estate. osg::Group* labelGroup = new osg::Group(); Decluttering::setEnabled( labelGroup->getOrCreateStateSet(), true ); annoGroup->addChild( labelGroup ); // Style our labels: Style labelStyle; labelStyle.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_CENTER; labelStyle.getOrCreate<TextSymbol>()->fill()->color() = Color::Yellow; // A lat/long SRS for specifying points. const SpatialReference* geoSRS = mapNode->getMapSRS()->getGeographicSRS(); //-------------------------------------------------------------------- // A series of place nodes (an icon with a text label) { Style pin; pin.getOrCreate<IconSymbol>()->url()->setLiteral( "../data/placemark32.png" ); // bunch of pins: labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -74.00, 40.71), "New York" , pin)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -77.04, 38.85), "Washington, DC", pin)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS,-118.40, 33.93), "Los Angeles" , pin)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -71.03, 42.37), "Boston" , pin)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS,-157.93, 21.35), "Honolulu" , pin)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, 139.75, 35.68), "Tokyo" , pin)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -90.25, 29.98), "New Orleans" , pin)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -80.28, 25.82), "Miami" , pin)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS,-117.17, 32.72), "San Diego" , pin)); // test with an LOD: osg::LOD* lod = new osg::LOD(); lod->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, 14.68, 50.0), "Prague", pin), 0.0, 1e6); labelGroup->addChild( lod ); // absolute altitude: labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -87.65, 41.90, 1000, ALTMODE_ABSOLUTE), "Chicago" , pin)); } //-------------------------------------------------------------------- // a box that follows lines of latitude (rhumb line interpolation, the default) { Geometry* geom = new 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) ); Style geomStyle; geomStyle.getOrCreate<LineSymbol>()->stroke()->color() = Color::Cyan; geomStyle.getOrCreate<LineSymbol>()->stroke()->width() = 5.0f; geomStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; geomStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_GPU; FeatureNode* gnode = new FeatureNode(mapNode, new Feature(geom, geoSRS, geomStyle)); annoGroup->addChild( gnode ); labelGroup->addChild( new LabelNode(mapNode, GeoPoint(geoSRS,-30, 50), "Rhumb line polygon", labelStyle) ); } //-------------------------------------------------------------------- // another rhumb box that crosses the antimeridian { Geometry* geom = new Polygon(); geom->push_back( -160., -30. ); geom->push_back( 150., -20. ); geom->push_back( 160., -45. ); geom->push_back( -150., -40. ); Style geomStyle; geomStyle.getOrCreate<LineSymbol>()->stroke()->color() = Color::Lime; geomStyle.getOrCreate<LineSymbol>()->stroke()->width() = 3.0f; geomStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; geomStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_GPU; FeatureNode* gnode = new FeatureNode(mapNode, new Feature(geom, geoSRS, geomStyle)); annoGroup->addChild( gnode ); labelGroup->addChild( new LabelNode(mapNode, GeoPoint(geoSRS, -175, -35), "Antimeridian polygon", labelStyle) ); } //-------------------------------------------------------------------- // A path using great-circle interpolation. { Geometry* path = new LineString(); path->push_back( osg::Vec3d(-74, 40.714, 0) ); // New York path->push_back( osg::Vec3d(139.75, 35.68, 0) ); // Tokyo Style pathStyle; pathStyle.getOrCreate<LineSymbol>()->stroke()->color() = Color::Red; pathStyle.getOrCreate<LineSymbol>()->stroke()->width() = 3.0f; pathStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; pathStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_GPU; Feature* pathFeature = new Feature(path, geoSRS, pathStyle); pathFeature->geoInterp() = GEOINTERP_GREAT_CIRCLE; //OE_INFO << "Path extent = " << pathFeature->getExtent().toString() << std::endl; FeatureNode* pathNode = new FeatureNode(mapNode, pathFeature); annoGroup->addChild( pathNode ); labelGroup->addChild( new LabelNode(mapNode, GeoPoint(geoSRS,-170, 61.2), "Great circle path", labelStyle) ); } //-------------------------------------------------------------------- // Two circle segments around New Orleans. { 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( mapNode, 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 ); editorGroup->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( mapNode, 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 ); editorGroup->addChild( new CircleNodeEditor( circle ) ); } //-------------------------------------------------------------------- // An extruded ellipse around Miami. { Style ellipseStyle; ellipseStyle.getOrCreate<PolygonSymbol>()->fill()->color() = Color(Color::Orange, 0.75); ellipseStyle.getOrCreate<ExtrusionSymbol>()->height() = 250000.0; // meters MSL EllipseNode* ellipse = new EllipseNode( mapNode, 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 ); editorGroup->addChild( new EllipseNodeEditor( ellipse ) ); } { Style ellipseStyle; ellipseStyle.getOrCreate<PolygonSymbol>()->fill()->color() = Color(Color::Blue, 0.75); ellipseStyle.getOrCreate<ExtrusionSymbol>()->height() = 250000.0; // meters MSL EllipseNode* ellipse = new EllipseNode( mapNode, 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 ); editorGroup->addChild( new EllipseNodeEditor( ellipse ) ); } //-------------------------------------------------------------------- { // A rectangle around San Diego Style rectStyle; 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( mapNode, GeoPoint(geoSRS, -117.172, 32.721), Distance(300, Units::KILOMETERS ), Distance(600, Units::KILOMETERS ), rectStyle); annoGroup->addChild( rect ); editorGroup->addChild( new RectangleNodeEditor( rect ) ); } //-------------------------------------------------------------------- // An extruded polygon roughly the shape of Utah. Here we demonstrate the // FeatureNode, where you create a geographic geometry and use it as an // annotation. { Geometry* utah = new 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() = 250000.0; // meters MSL utahStyle.getOrCreate<PolygonSymbol>()->fill()->color() = Color(Color::White, 0.8); Feature* utahFeature = new Feature(utah, geoSRS, utahStyle); FeatureNode* featureNode = new FeatureNode(mapNode, utahFeature); annoGroup->addChild( featureNode ); } //-------------------------------------------------------------------- // an image overlay. { ImageOverlay* imageOverlay = 0L; osg::Image* image = osgDB::readImageFile( "../data/USFLAG.TGA" ); if ( image ) { imageOverlay = new ImageOverlay(mapNode, image); imageOverlay->setBounds( Bounds( -100.0, 35.0, -90.0, 40.0) ); annoGroup->addChild( imageOverlay ); editorGroup->addChild( new ImageOverlayEditor( imageOverlay ) ); } } //-------------------------------------------------------------------- // install decoration. These change the appearance of an Annotation // based on some user action. // highlight annotation upon hover by default: DecorationInstaller highlightInstaller("hover", new HighlightDecoration()); annoGroup->accept( highlightInstaller ); // scale labels when hovering: DecorationInstaller scaleInstaller("hover", new ScaleDecoration(1.1f)); labelGroup->accept( scaleInstaller ); // install an event handler for picking and hovering. AnnotationEventCallback* cb = new AnnotationEventCallback(); cb->addHandler( new MyAnnoEventHandler() ); annoGroup->addEventCallback( cb ); //-------------------------------------------------------------------- // initialize the viewer: viewer.setSceneData( root ); viewer.getCamera()->addCullCallback( new AutoClipPlaneCullCallback(mapNode) ); viewer.addEventHandler(new osgViewer::StatsHandler()); viewer.addEventHandler(new osgViewer::WindowSizeHandler()); viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())); return viewer.run(); }
int main(int argc, char** argv) { osg::Group* root = new osg::Group(); // try to load an earth file. osg::ArgumentParser arguments(&argc,argv); osgViewer::Viewer viewer(arguments); viewer.setCameraManipulator( new EarthManipulator() ); // load an earth file and parse demo arguments osg::Node* node = MapNodeHelper().load(arguments, &viewer); if ( !node ) return usage(argv); root->addChild( node ); // find the map node that we loaded. MapNode* mapNode = MapNode::findMapNode(node); if ( !mapNode ) return usage(argv); // Group to hold all our annotation elements. osg::Group* annoGroup = new osg::Group(); root->addChild( annoGroup ); // Make a group for labels osg::Group* labelGroup = new osg::Group(); annoGroup->addChild( labelGroup ); osg::Group* editGroup = new osg::Group(); root->addChild( editGroup ); // Style our labels: Style labelStyle; labelStyle.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_CENTER; labelStyle.getOrCreate<TextSymbol>()->fill()->color() = Color::Yellow; // A lat/long SRS for specifying points. const SpatialReference* geoSRS = mapNode->getMapSRS()->getGeographicSRS(); //-------------------------------------------------------------------- // A series of place nodes (an icon with a text label) { Style pm; pm.getOrCreate<IconSymbol>()->url()->setLiteral( "../data/placemark32.png" ); pm.getOrCreate<IconSymbol>()->declutter() = true; pm.getOrCreate<TextSymbol>()->halo() = Color("#5f5f5f"); // bunch of pins: labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -74.00, 40.71), "New York" , pm)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -77.04, 38.85), "Washington, DC", pm)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS,-118.40, 33.93), "Los Angeles" , pm)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -71.03, 42.37), "Boston" , pm)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS,-157.93, 21.35), "Honolulu" , pm)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, 139.75, 35.68), "Tokyo" , pm)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -90.25, 29.98), "New Orleans" , pm)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -80.28, 25.82), "Miami" , pm)); labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS,-117.17, 32.72), "San Diego" , pm)); // test with an LOD: osg::LOD* lod = new osg::LOD(); lod->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, 14.68, 50.0), "Prague", pm), 0.0, 2e6); labelGroup->addChild( lod ); // absolute altitude: labelGroup->addChild( new PlaceNode(mapNode, GeoPoint(geoSRS, -87.65, 41.90, 1000, ALTMODE_ABSOLUTE), "Chicago", pm)); } //-------------------------------------------------------------------- // a box that follows lines of latitude (rhumb line interpolation, the default) { Geometry* geom = new 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::Cyan; 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(mapNode, feature, geomStyle); annoGroup->addChild( fnode ); labelGroup->addChild( new LabelNode(mapNode, GeoPoint(geoSRS,-30, 50), "Rhumb line polygon", labelStyle) ); } //-------------------------------------------------------------------- // another rhumb box that crosses the antimeridian { Geometry* geom = new 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(mapNode, feature, geomStyle); annoGroup->addChild( gnode ); labelGroup->addChild( new LabelNode(mapNode, GeoPoint(geoSRS, -175, -35), "Antimeridian polygon", labelStyle) ); } //-------------------------------------------------------------------- // A path using great-circle interpolation. // Keep a pointer to it so we can modify it later on. FeatureNode* pathNode = 0; { Geometry* path = new LineString(); path->push_back( osg::Vec3d(-74, 40.714, 0) ); // New York path->push_back( osg::Vec3d(139.75, 35.68, 0) ); // Tokyo 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>()->tessellationSize() = 75000; pathStyle.getOrCreate<PointSymbol>()->size() = 5; pathStyle.getOrCreate<PointSymbol>()->fill()->color() = Color::Red; pathStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; pathStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_GPU; //OE_INFO << "Path extent = " << pathFeature->getExtent().toString() << std::endl; pathNode = new FeatureNode(mapNode, pathFeature, pathStyle); annoGroup->addChild( pathNode ); labelGroup->addChild( new LabelNode(mapNode, GeoPoint(geoSRS,-170, 61.2), "Great circle path", labelStyle) ); } //-------------------------------------------------------------------- // Two circle segments around New Orleans. { 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( mapNode, 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( mapNode, 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) ); } //-------------------------------------------------------------------- // An extruded ellipse around Miami. { Style ellipseStyle; ellipseStyle.getOrCreate<PolygonSymbol>()->fill()->color() = Color(Color::Orange, 0.75); ellipseStyle.getOrCreate<ExtrusionSymbol>()->height() = 250000.0; // meters MSL EllipseNode* ellipse = new EllipseNode( mapNode, 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; // meters MSL EllipseNode* ellipse = new EllipseNode( mapNode, 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) ); } //-------------------------------------------------------------------- { // A rectangle around San Diego Style rectStyle; 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( mapNode, GeoPoint(geoSRS, -117.172, 32.721), Distance(300, Units::KILOMETERS ), Distance(600, Units::KILOMETERS ), rectStyle); annoGroup->addChild( rect ); editGroup->addChild( new RectangleNodeEditor(rect) ); } //-------------------------------------------------------------------- // An extruded polygon roughly the shape of Utah. Here we demonstrate the // FeatureNode, where you create a geographic geometry and use it as an // annotation. { Geometry* utah = new 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() = 250000.0; // meters MSL utahStyle.getOrCreate<PolygonSymbol>()->fill()->color() = Color(Color::White, 0.8); Feature* utahFeature = new Feature(utah, geoSRS); FeatureNode* featureNode = new FeatureNode(mapNode, utahFeature, utahStyle); annoGroup->addChild( featureNode ); } //-------------------------------------------------------------------- // an image overlay. { ImageOverlay* imageOverlay = 0L; osg::Image* image = osgDB::readImageFile( "../data/USFLAG.TGA" ); if ( image ) { imageOverlay = new ImageOverlay(mapNode, image); imageOverlay->setBounds( Bounds( -100.0, 35.0, -90.0, 40.0) ); annoGroup->addChild( imageOverlay ); editGroup->addChild( new ImageOverlayEditor(imageOverlay) ); } } //-------------------------------------------------------------------- // initialize the viewer: viewer.setSceneData( root ); viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f); return viewer.run(); }