void PlaceNode::setText( const std::string& text ) { if ( !_dynamic ) { OE_WARN << LC << "Illegal state: cannot change a LabelNode that is not dynamic" << std::endl; return; } _text = text; for(unsigned i=0; i<_geode->getNumDrawables(); ++i) { osgText::Text* d = dynamic_cast<osgText::Text*>( _geode->getDrawable(i) ); if ( d ) { TextSymbol* symbol = _style.getOrCreate<TextSymbol>(); osgText::String::Encoding text_encoding = osgText::String::ENCODING_UNDEFINED; if ( symbol && symbol->encoding().isSet() ) { text_encoding = AnnotationUtils::convertTextSymbolEncoding(symbol->encoding().value()); } d->setText( text, text_encoding ); break; } } }
void createTrackSchema(TrackNodeFieldSchema& schema) { // draw the track name above the icon: TextSymbol* nameSymbol = new TextSymbol(); nameSymbol->pixelOffset()->set( 0, 2+TRACK_ICON_SIZE/2 ); nameSymbol->alignment() = TextSymbol::ALIGN_CENTER_BOTTOM; nameSymbol->halo()->color() = Color::Black; schema[TRACK_FIELD_NAME] = TrackNodeField(nameSymbol, false); }
void MGRSGraticule::setUpDefaultStyles() { if (!options().gzdStyle().isSet()) { LineSymbol* line = options().gzdStyle()->getOrCreate<LineSymbol>(); line->stroke()->color() = Color::Gray; line->stroke()->width() = 1.0; line->tessellation() = 20; TextSymbol* text = options().gzdStyle()->getOrCreate<TextSymbol>(); text->fill()->color() = Color(Color::White, 0.3f); text->halo()->color() = Color(Color::Black, 0.2f); text->alignment() = TextSymbol::ALIGN_CENTER_CENTER; } if (!options().sqidStyle().isSet()) { LineSymbol* line = options().sqidStyle()->getOrCreate<LineSymbol>(); line->stroke()->color() = Color(Color::White, 0.5f); line->stroke()->stipplePattern() = 0x1111; TextSymbol* text = options().sqidStyle()->getOrCreate<TextSymbol>(); text->fill()->color() = Color(Color::White, 0.3f); text->halo()->color() = Color(Color::Black, 0.1f); text->alignment() = TextSymbol::ALIGN_CENTER_CENTER; } }
TextSymbol::TextSymbol(const TextSymbol& rhs,const osg::CopyOp& copyop): Symbol(rhs, copyop), _fill(rhs._fill), _halo(rhs._halo), _haloOffset(rhs._haloOffset), _haloBackdropType(rhs._haloBackdropType), _haloImplementation(rhs._haloImplementation), _font(rhs._font), _size(rhs._size), _content(rhs._content), _priority(rhs._priority), _pixelOffset(rhs._pixelOffset), _onScreenRotation(rhs._onScreenRotation), _geographicCourse(rhs._geographicCourse), _provider(rhs._provider), _encoding(rhs._encoding), _alignment(rhs._alignment), _layout(rhs._layout), _declutter(rhs._declutter), _occlusionCull(rhs._occlusionCull), _occlusionCullAltitude(rhs._occlusionCullAltitude), _autoOffsetAlongLine(rhs._autoOffsetAlongLine), _autoOffsetPreferedPosition(rhs._autoOffsetPreferedPosition), _autoRotateAlongLine(rhs._autoRotateAlongLine), _autoOffsetGeomWKT(rhs.autoOffsetGeomWKT()) { }
MGRSGraticule::MGRSGraticule( MapNode* mapNode ) : UTMGraticule( 0L ) { _mapNode = mapNode; init(); if ( !_options->secondaryStyle().isSet() ) { LineSymbol* line = _options->secondaryStyle()->getOrCreate<LineSymbol>(); line->stroke()->color() = Color(Color::White, 0.5f); line->stroke()->stipple() = 0x1111; TextSymbol* text = _options->secondaryStyle()->getOrCreate<TextSymbol>(); text->fill()->color() = Color(Color::White, 0.3f); text->halo()->color() = Color(Color::Black, 0.1f); text->alignment() = TextSymbol::ALIGN_CENTER_CENTER; } _minDepthOffset = DepthOffsetUtils::createMinOffsetUniform(); _minDepthOffset->set( 11000.0f ); }
void GeodeticGraticule::initLabelPool(CameraData& cdata) { const osgEarth::SpatialReference* srs = osgEarth::SpatialReference::create("wgs84"); Style style; TextSymbol* text = style.getOrCreateSymbol<TextSymbol>(); text->alignment() = TextSymbol::ALIGN_CENTER_CENTER; text->fill()->color() = options().labelColor().get(); AltitudeSymbol* alt = style.getOrCreateSymbol<AltitudeSymbol>(); alt->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; unsigned int labelPoolSize = 8 * options().gridLines().get(); for (unsigned int i = 0; i < labelPoolSize; i++) { GeoPoint pt(srs, 0,0,0); LabelNode* label = new LabelNode(_mapNode.get(), pt, "0,0"); label->setDynamic(true); label->setStyle(style); cdata._labelPool.push_back(label); } }
GraticuleLabelingEngine::GraticuleLabelingEngine(const SpatialReference* srs) { _srs = srs; // Set up the symbology for x-axis labels TextSymbol* xText = _xLabelStyle.getOrCreate<TextSymbol>(); xText->alignment() = TextSymbol::ALIGN_CENTER_BOTTOM; xText->halo()->color().set(0, 0, 0, 1); xText->declutter() = false; // Set up the symbology for y-axis labels TextSymbol* yText = _yLabelStyle.getOrCreate<TextSymbol>(); yText->alignment() = TextSymbol::ALIGN_LEFT_BOTTOM; yText->halo()->color().set(0, 0, 0, 1); yText->declutter() = false; }
/** * Creates a field schema that we'll later use as a labeling template for * TrackNode instances. */ void createFieldSchema( TrackNodeFieldSchema& schema ) { // draw the track name above the icon: TextSymbol* nameSymbol = new TextSymbol(); nameSymbol->pixelOffset()->set( 0, 2+ICON_SIZE/2 ); nameSymbol->alignment() = TextSymbol::ALIGN_CENTER_BOTTOM; nameSymbol->halo()->color() = Color::Black; nameSymbol->size() = nameSymbol->size()->eval() + 2.0f; schema[FIELD_NAME] = TrackNodeField(nameSymbol, false); // false => static label (won't change after set) // draw the track coordinates below the icon: TextSymbol* posSymbol = new TextSymbol(); posSymbol->pixelOffset()->set( 0, -2-ICON_SIZE/2 ); posSymbol->alignment() = TextSymbol::ALIGN_CENTER_TOP; posSymbol->fill()->color() = Color::Yellow; posSymbol->size() = posSymbol->size()->eval() - 2.0f; schema[FIELD_POSITION] = TrackNodeField(posSymbol, true); // true => may change at runtime // draw some other field to the left: TextSymbol* numberSymbol = new TextSymbol(); numberSymbol->pixelOffset()->set( -2-ICON_SIZE/2, 0 ); numberSymbol->alignment() = TextSymbol::ALIGN_RIGHT_CENTER; schema[FIELD_NUMBER] = TrackNodeField(numberSymbol, false); }
void UTMGraticule::rebuild() { if (_root.valid() == false) return; osg::ref_ptr<const Map> map; if (!_map.lock(map)) return; // clear everything out _root->removeChildren( 0, _root->getNumChildren() ); // requires a geocentric map if ( !map->isGeocentric() ) { OE_WARN << LC << "Projected map mode is not yet supported" << std::endl; return; } const Profile* mapProfile = map->getProfile(); _profile = Profile::create( mapProfile->getSRS(), mapProfile->getExtent().xMin(), mapProfile->getExtent().yMin(), mapProfile->getExtent().xMax(), mapProfile->getExtent().yMax(), 8, 4 ); _featureProfile = new FeatureProfile(_profile->getSRS()); //todo: do this right.. osg::StateSet* set = this->getOrCreateStateSet(); GLUtils::setLighting(set, 0); set->setMode( GL_BLEND, 1 ); set->setMode( GL_CLIP_DISTANCE0, 1 ); // set up default options if the caller did not supply them if ( !options().gzdStyle().isSet() ) { options().gzdStyle() = Style(); LineSymbol* line = options().gzdStyle()->getOrCreate<LineSymbol>(); line->stroke()->color() = Color::Gray; line->stroke()->width() = 1.0; line->tessellation() = 20; TextSymbol* text = options().gzdStyle()->getOrCreate<TextSymbol>(); text->fill()->color() = Color(Color::White, 0.3f); text->halo()->color() = Color(Color::Black, 0.2f); text->alignment() = TextSymbol::ALIGN_CENTER_CENTER; } // initialize the UTM sector tables for this profile. _utmData.rebuild(_profile.get()); // now build the lateral tiles for the GZD level. for( UTMData::SectorTable::iterator i = _utmData.sectorTable().begin(); i != _utmData.sectorTable().end(); ++i ) { osg::Node* tile = _utmData.buildGZDTile(i->first, i->second, options().gzdStyle().get(), _featureProfile.get(), map.get()); if ( tile ) _root->addChild( tile ); } }
osg::Node* UTMGraticule::buildGZDTile( const std::string& name, const GeoExtent& extent ) { osg::Group* group = new osg::Group(); Style lineStyle; lineStyle.add( _options->primaryStyle()->get<LineSymbol>() ); lineStyle.add( _options->primaryStyle()->get<AltitudeSymbol>() ); //const Style& lineStyle = *_options->lineStyle(); //Style textStyle = *_options->textStyle(); bool hasText = _options->primaryStyle()->get<TextSymbol>() != 0L; GeometryCompiler compiler; osg::ref_ptr<Session> session = new Session( _mapNode->getMap() ); FilterContext context( session.get(), _featureProfile.get(), extent ); // make sure we get sufficient tessellation: compiler.options().maxGranularity() = 1.0; FeatureList features; // longitudinal line: LineString* lon = new LineString(2); lon->push_back( osg::Vec3d(extent.xMin(), extent.yMax(), 0) ); lon->push_back( osg::Vec3d(extent.xMin(), extent.yMin(), 0) ); Feature* lonFeature = new Feature(lon, extent.getSRS()); lonFeature->geoInterp() = GEOINTERP_GREAT_CIRCLE; features.push_back( lonFeature ); // latitudinal line: LineString* lat = new LineString(2); lat->push_back( osg::Vec3d(extent.xMin(), extent.yMin(), 0) ); lat->push_back( osg::Vec3d(extent.xMax(), extent.yMin(), 0) ); Feature* latFeature = new Feature(lat, extent.getSRS()); latFeature->geoInterp() = GEOINTERP_RHUMB_LINE; features.push_back( latFeature ); // top lat line at 84N if ( extent.yMax() == 84.0 ) { LineString* lat = new LineString(2); lat->push_back( osg::Vec3d(extent.xMin(), extent.yMax(), 0) ); lat->push_back( osg::Vec3d(extent.xMax(), extent.yMax(), 0) ); Feature* latFeature = new Feature(lat, extent.getSRS()); latFeature->geoInterp() = GEOINTERP_RHUMB_LINE; features.push_back( latFeature ); } osg::Node* geomNode = compiler.compile(features, lineStyle, context); if ( geomNode ) group->addChild( geomNode ); // get the geocentric tile center: osg::Vec3d tileCenter; extent.getCentroid( tileCenter.x(), tileCenter.y() ); osg::Vec3d centerECEF; extent.getSRS()->transformToECEF( tileCenter, centerECEF ); if ( hasText ) { osg::Vec3d west, east; extent.getSRS()->transformToECEF(osg::Vec3d(extent.xMin(),tileCenter.y(),0), west ); extent.getSRS()->transformToECEF(osg::Vec3d(extent.xMax(),tileCenter.y(),0), east ); TextSymbol* textSym = _options->primaryStyle()->getOrCreate<TextSymbol>(); textSym->size() = (west-east).length() / 3.0; TextSymbolizer ts( textSym ); osg::Geode* textGeode = new osg::Geode(); textGeode->getOrCreateStateSet()->setRenderBinDetails( 9998, "DepthSortedBin" ); textGeode->getOrCreateStateSet()->setAttributeAndModes( _depthAttribute, 1 ); osg::Drawable* d = ts.create(name); d->getOrCreateStateSet()->setRenderBinToInherit(); textGeode->addDrawable(d); osg::MatrixTransform* mt = new osg::MatrixTransform(ECEF::createLocalToWorld(centerECEF)); mt->addChild(textGeode); group->addChild(mt); } group = buildGZDChildren( group, name ); group = ClusterCullingFactory::createAndInstall( group, centerECEF )->asGroup(); return group; }
void UTMGraticule::init() { if ( !_mapNode.valid() ) { OE_WARN << LC << "Illegal NULL map node" << std::endl; return; } if ( !_mapNode->isGeocentric() ) { OE_WARN << LC << "Projected map mode is not yet supported" << std::endl; return; } // safely generate a unique ID for this graticule: _id = Registry::instance()->createUID(); { Threading::ScopedMutexLock lock( s_graticuleMutex ); s_graticuleRegistry[_id] = this; } const Profile* mapProfile = _mapNode->getMap()->getProfile(); _profile = Profile::create( mapProfile->getSRS(), mapProfile->getExtent().xMin(), mapProfile->getExtent().yMin(), mapProfile->getExtent().xMax(), mapProfile->getExtent().yMax(), 8, 4 ); _featureProfile = new FeatureProfile(_profile->getSRS()); //todo: do this right.. osg::StateSet* set = this->getOrCreateStateSet(); set->setMode( GL_LIGHTING, 0 ); set->setMode( GL_BLEND, 1 ); // set up default options if the caller did not supply them if ( !_options.isSet() ) { _options->primaryStyle()= Style(); LineSymbol* line = _options->primaryStyle()->getOrCreate<LineSymbol>(); line->stroke()->color() = Color::Gray; line->stroke()->width() = 1.0; line->tessellation() = 20; AltitudeSymbol* alt = _options->primaryStyle()->getOrCreate<AltitudeSymbol>(); //alt->verticalOffset() = NumericExpression(4900.0); TextSymbol* text = _options->primaryStyle()->getOrCreate<TextSymbol>(); text->fill()->color() = Color(Color::White, 0.3f); text->halo()->color() = Color(Color::Black, 0.2f); text->alignment() = TextSymbol::ALIGN_CENTER_CENTER; } // make the shared depth attr: _depthAttribute = new osg::Depth(osg::Depth::LEQUAL,0,1,false); // this will intialize the graph. rebuild(); }
void TextSymbol::parseSLD(const Config& c, Style& style) { TextSymbol defaults; if ( match(c.key(), "text-fill") || match(c.key(), "text-color") ) { style.getOrCreate<TextSymbol>()->fill()->color() = Color(c.value()); } else if ( match(c.key(), "text-fill-opacity") ) { style.getOrCreate<TextSymbol>()->fill()->color().a() = as<float>( c.value(), 1.0f ); } else if ( match(c.key(), "text-size") ) { style.getOrCreate<TextSymbol>()->size() = NumericExpression( c.value() ); } else if ( match(c.key(), "text-font") ) { style.getOrCreate<TextSymbol>()->font() = c.value(); } else if ( match(c.key(), "text-halo") || match(c.key(), "text-halo-color") ) { style.getOrCreate<TextSymbol>()->halo()->color() = htmlColorToVec4f( c.value() ); } else if ( match(c.key(), "text-halo-offset") ) { style.getOrCreate<TextSymbol>()->haloOffset() = as<float>(c.value(), defaults.haloOffset().get() ); } else if ( match(c.key(), "text-halo-backdrop-type") ) { if ( match(c.value(), "right-bottom") ) style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_BOTTOM_RIGHT; else if ( match(c.value(), "right-center") ) style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_CENTER_RIGHT; else if ( match(c.value(), "right-top") ) style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_TOP_RIGHT; else if ( match(c.value(), "center-bottom") ) style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_BOTTOM_CENTER; else if ( match(c.value(), "center-top") ) style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_TOP_CENTER; else if ( match(c.value(), "left-bottom") ) style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_BOTTOM_LEFT; else if ( match(c.value(), "left-center") ) style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_CENTER_LEFT; else if ( match(c.value(), "left-top") ) style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::DROP_SHADOW_TOP_LEFT; else if ( match(c.value(), "outline") ) style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::OUTLINE; else if ( match(c.value(), "none") ) style.getOrCreate<TextSymbol>()->haloBackdropType() = osgText::Text::NONE; } else if ( match(c.key(), "text-halo-implementation") ) { if ( match(c.value(), "polygon-offset") ) style.getOrCreate<TextSymbol>()->haloImplementation() = osgText::Text::POLYGON_OFFSET; else if ( match(c.value(), "no-depth-buffer") ) style.getOrCreate<TextSymbol>()->haloImplementation() = osgText::Text::NO_DEPTH_BUFFER; else if ( match(c.value(), "depth-range") ) style.getOrCreate<TextSymbol>()->haloImplementation() = osgText::Text::DEPTH_RANGE; else if ( match(c.value(), "stencil-buffer") ) style.getOrCreate<TextSymbol>()->haloImplementation() = osgText::Text::STENCIL_BUFFER; else if ( match(c.value(), "delayed-depth-writes") ) style.getOrCreate<TextSymbol>()->haloImplementation() = osgText::Text::DELAYED_DEPTH_WRITES; } else if ( match(c.key(), "text-remove-duplicate-labels") ) { if ( c.value() == "true" ) style.getOrCreate<TextSymbol>()->removeDuplicateLabels() = true; else if (c.value() == "false") style.getOrCreate<TextSymbol>()->removeDuplicateLabels() = false; } else if ( match(c.key(), "text-align") ) { if ( match(c.value(), "left-top") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_LEFT_TOP; else if ( match(c.value(), "left-center") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_LEFT_CENTER; else if ( match(c.value(), "left-bottom") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_LEFT_BOTTOM; else if ( match(c.value(), "center-top") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_TOP; else if ( match(c.value(), "center-center") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_CENTER; else if ( match(c.value(), "center-bottom") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_BOTTOM; else if ( match(c.value(), "right-top") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_RIGHT_TOP; else if ( match(c.value(), "right-center") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_RIGHT_CENTER; else if ( match(c.value(), "right-bottom") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_RIGHT_BOTTOM; else if ( match(c.value(), "left-base-line") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_LEFT_BASE_LINE; else if ( match(c.value(), "center-base-line") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_BASE_LINE; else if ( match(c.value(), "right-base-line") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_RIGHT_BASE_LINE; else if ( match(c.value(), "left-bottom-base-line") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_LEFT_BOTTOM_BASE_LINE; else if ( match(c.value(), "center-bottom-base-line") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_CENTER_BOTTOM_BASE_LINE; else if ( match(c.value(), "right-bottom-base-line") ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_RIGHT_BOTTOM_BASE_LINE; else if ( match(c.value(), "base-line" ) ) style.getOrCreate<TextSymbol>()->alignment() = TextSymbol::ALIGN_BASE_LINE; } else if ( match(c.key(), "text-layout") ) { if ( match(c.value(), "ltr") ) style.getOrCreate<TextSymbol>()->layout() = TextSymbol::LAYOUT_LEFT_TO_RIGHT; else if ( match(c.value(), "rtl" ) ) style.getOrCreate<TextSymbol>()->layout() = TextSymbol::LAYOUT_RIGHT_TO_LEFT; else if ( match(c.value(), "vertical" ) ) style.getOrCreate<TextSymbol>()->layout() = TextSymbol::LAYOUT_VERTICAL; } else if ( match(c.key(), "text-content") || match(c.key(), "text") ) { style.getOrCreate<TextSymbol>()->content() = StringExpression( c.value() ); } else if ( match(c.key(), "text-priority") ) { style.getOrCreate<TextSymbol>()->priority() = NumericExpression( c.value() ); } else if ( match(c.key(), "text-provider") ) { style.getOrCreate<TextSymbol>()->provider() = c.value(); } else if ( match(c.key(), "text-encoding") ) { if (match(c.value(), "utf-8")) style.getOrCreate<TextSymbol>()->encoding() = TextSymbol::ENCODING_UTF8; else if (match(c.value(), "utf-16")) style.getOrCreate<TextSymbol>()->encoding() = TextSymbol::ENCODING_UTF16; else if (match(c.value(), "utf-32")) style.getOrCreate<TextSymbol>()->encoding() = TextSymbol::ENCODING_UTF32; else if (match(c.value(), "ascii")) style.getOrCreate<TextSymbol>()->encoding() = TextSymbol::ENCODING_ASCII; else style.getOrCreate<TextSymbol>()->encoding() = TextSymbol::ENCODING_ASCII; } else if ( match(c.key(), "text-declutter") ) { style.getOrCreate<TextSymbol>()->declutter() = as<bool>(c.value(), defaults.declutter().get() ); } else if ( match(c.key(), "text-occlusion-cull") ) { style.getOrCreate<TextSymbol>()->occlusionCull() = as<bool>(c.value(), defaults.occlusionCull().get() ); } else if ( match(c.key(), "text-occlusion-cull-altitude") ) { style.getOrCreate<TextSymbol>()->occlusionCullAltitude() = as<double>(c.value(), defaults.occlusionCullAltitude().get() ); } else if ( match(c.key(), "text-script") ) { style.getOrCreate<TextSymbol>()->script() = StringExpression(c.value()); } else if ( match(c.key(), "text-offset-x") ) { style.getOrCreate<TextSymbol>()->pixelOffset()->x() = as<double>(c.value(), defaults.pixelOffset()->x() ); } else if ( match(c.key(), "text-offset-y") ) { style.getOrCreate<TextSymbol>()->pixelOffset()->y() = as<double>(c.value(), defaults.pixelOffset()->y() ); } else if ( match(c.key(), "text-rotation") ) { style.getOrCreate<TextSymbol>()->onScreenRotation() = NumericExpression( c.value() ); } else if ( match(c.key(), "text-geographic-course") ) { style.getOrCreate<TextSymbol>()->geographicCourse() = NumericExpression( c.value() ); } }
void KML_Placemark::build( xml_node<>* node, KMLContext& cx ) { Style masterStyle; std::string styleUrl = getValue(node, "styleurl"); if (!styleUrl.empty()) { // process a "stylesheet" style const Style* ref_style = cx._sheet->getStyle( styleUrl, false ); if (ref_style) { masterStyle = masterStyle.combineWith(*ref_style); } } xml_node<>* style = node->first_node("style", 0, false); if ( style ) { // process an "inline" style KML_Style kmlStyle; kmlStyle.scan(style, cx); masterStyle = masterStyle.combineWith(cx._activeStyle); } // parse the geometry. the placemark must have geometry to be valid. The // geometry parse may optionally specify an altitude mode as well. KML_Geometry geometry; geometry.build(node, cx, masterStyle); Geometry* allGeom = geometry._geom.get(); if ( allGeom ) { GeometryIterator giter( allGeom, false ); while( giter.hasMore() ) { Geometry* geom = giter.next(); Style style = masterStyle; AltitudeSymbol* alt = style.get<AltitudeSymbol>(); if ( geom && geom->getTotalPointCount() > 0 ) { // resolve the proper altitude mode for the anchor point AltitudeMode altMode = ALTMODE_RELATIVE; if (alt && !alt->clamping().isSetTo( alt->CLAMP_TO_TERRAIN ) && !alt->clamping().isSetTo( alt->CLAMP_RELATIVE_TO_TERRAIN ) ) { altMode = ALTMODE_ABSOLUTE; } GeoPoint position(cx._srs.get(), geom->getBounds().center(), altMode); // check for symbols. ModelSymbol* model = style.get<ModelSymbol>(); IconSymbol* icon = style.get<IconSymbol>(); TextSymbol* text = style.get<TextSymbol>(); // for a single point placemark, apply the default icon and text symbols // if none are specified in the KML. if (geom->getTotalPointCount() == 1) { if (!model && !icon && cx._options->defaultIconSymbol().valid()) { icon = cx._options->defaultIconSymbol().get(); style.add(icon); } if (!text && cx._options->defaultTextSymbol().valid()) { text = cx._options->defaultTextSymbol().get(); style.add(text); } } // the annotation name: std::string name = getValue(node, "name"); if (!name.empty()) { OE_INFO << LC << "Placemark: " << name << std::endl; } AnnotationNode* featureNode = 0L; AnnotationNode* iconNode = 0L; AnnotationNode* modelNode = 0L; // one coordinate? It's a place marker or a label. if ( (model || icon || text) && geom->getTotalPointCount() == 1 ) { // if there's a model, render that - models do NOT get labels. if ( model ) { ModelNode* node = new ModelNode( cx._mapNode, style, cx._dbOptions.get() ); node->setPosition( position ); // model scale: if ( cx._options->modelScale() != 1.0f ) { float s = *cx._options->modelScale(); node->getPositionAttitudeTransform()->setScale(osg::Vec3d(s,s,s)); } // model local tangent plane rotation: if ( !cx._options->modelRotation()->zeroRotation() ) { node->getPositionAttitudeTransform()->setAttitude( *cx._options->modelRotation() ); } modelNode = node; } // is there a label? else if ( !name.empty() ) { if ( !text ) { text = style.getOrCreate<TextSymbol>(); text->encoding() = TextSymbol::ENCODING_UTF8; } text->content()->setLiteral( name ); } // is there an icon? if ( icon ) { PlaceNode* placeNode = new PlaceNode( position ); placeNode->setStyle(style, cx._dbOptions.get()); iconNode = placeNode; } else if ( !model && text && !name.empty() ) { // note: models do not get labels. iconNode = new LabelNode(); iconNode->setStyle(style); } } // multiple coords? feature: if ( geom->getTotalPointCount() > 1 ) { // Remove symbols that we have already processed so the geometry // compiler doesn't get confused. if ( model ) style.removeSymbol( model ); if ( icon ) style.removeSymbol( icon ); if ( text ) style.removeSymbol( text ); Feature* feature = new Feature(geom, cx._srs.get(), style); featureNode = new FeatureNode(feature ); featureNode->setMapNode( cx._mapNode ); } if ( iconNode ) { Registry::objectIndex()->tagNode( iconNode, iconNode ); } if ( modelNode ) { Registry::objectIndex()->tagNode( modelNode, modelNode ); } if ( featureNode ) { Registry::objectIndex()->tagNode( featureNode, featureNode ); } // assemble the results: if ( (iconNode || modelNode) && featureNode ) { osg::Group* group = new osg::Group(); group->addChild( featureNode ); if ( iconNode ) group->addChild( iconNode ); if ( modelNode ) group->addChild( modelNode ); cx._groupStack.top()->addChild( group ); if ( iconNode ) KML_Feature::build( node, cx, iconNode ); if ( modelNode ) KML_Feature::build( node, cx, modelNode ); if ( featureNode ) KML_Feature::build( node, cx, featureNode ); } else { if ( iconNode ) { if ( cx._options->iconAndLabelGroup().valid() ) { cx._options->iconAndLabelGroup()->addChild( iconNode ); } else { cx._groupStack.top()->addChild( iconNode ); } KML_Feature::build( node, cx, iconNode ); } if ( modelNode ) { cx._groupStack.top()->addChild( modelNode ); KML_Feature::build( node, cx, modelNode ); } if ( featureNode ) { osg::Node* child = featureNode; // If this feature node is map-clamped, we most likely need a depth-offset // shader to prevent z-fighting with the terrain. if (alt && alt->clamping() == alt->CLAMP_TO_TERRAIN && alt->technique() == alt->TECHNIQUE_MAP) { DepthOffsetGroup* g = new DepthOffsetGroup(); g->addChild( featureNode ); child = g; } cx._groupStack.top()->addChild( child ); KML_Feature::build( node, cx, featureNode ); } } } } } }
void UTMGraticule::rebuild() { // clear everything out this->removeChildren( 0, this->getNumChildren() ); // requires a map node if ( !getMapNode() ) { return; } // requires a geocentric map if ( !getMapNode()->isGeocentric() ) { OE_WARN << LC << "Projected map mode is not yet supported" << std::endl; return; } const Profile* mapProfile = getMapNode()->getMap()->getProfile(); _profile = Profile::create( mapProfile->getSRS(), mapProfile->getExtent().xMin(), mapProfile->getExtent().yMin(), mapProfile->getExtent().xMax(), mapProfile->getExtent().yMax(), 8, 4 ); _featureProfile = new FeatureProfile(_profile->getSRS()); //todo: do this right.. osg::StateSet* set = this->getOrCreateStateSet(); set->setMode( GL_LIGHTING, 0 ); set->setMode( GL_BLEND, 1 ); // set up default options if the caller did not supply them if ( !_options.isSet() ) { _options->primaryStyle() = Style(); LineSymbol* line = _options->primaryStyle()->getOrCreate<LineSymbol>(); line->stroke()->color() = Color::Gray; line->stroke()->width() = 1.0; line->tessellation() = 20; AltitudeSymbol* alt = _options->primaryStyle()->getOrCreate<AltitudeSymbol>(); TextSymbol* text = _options->primaryStyle()->getOrCreate<TextSymbol>(); text->fill()->color() = Color(Color::White, 0.3f); text->halo()->color() = Color(Color::Black, 0.2f); text->alignment() = TextSymbol::ALIGN_CENTER_CENTER; } // rebuild the graph: _root = new DrapeableNode( getMapNode(), false ); this->addChild( _root ); #if 0 // set up depth offsetting. osg::StateSet* s = _root->getOrCreateStateSet(); s->setAttributeAndModes( DepthOffsetUtils::getOrCreateProgram(), 1 ); s->addUniform( DepthOffsetUtils::getIsNotTextUniform() ); osg::Uniform* u = DepthOffsetUtils::createMinOffsetUniform(); u->set( 10000.0f ); s->addUniform( u ); #endif // build the base Grid Zone Designator (GZD) loolup table. This is a table // that maps the GZD string to its extent. static std::string s_gzdRows( "CDEFGHJKLMNPQRSTUVWX" ); const SpatialReference* geosrs = _profile->getSRS()->getGeographicSRS(); // build the lateral zones: for( unsigned zone = 0; zone < 60; ++zone ) { for( unsigned row = 0; row < s_gzdRows.size(); ++row ) { double yMaxExtra = row == s_gzdRows.size()-1 ? 4.0 : 0.0; // extra 4 deg for row X GeoExtent cellExtent( geosrs, -180.0 + double(zone)*6.0, -80.0 + row*8.0, -180.0 + double(zone+1)*6.0, -80.0 + double(row+1)*8.0 + yMaxExtra ); _gzd[ Stringify() << (zone+1) << s_gzdRows[row] ] = cellExtent; } } // the polar zones (UPS): _gzd["1Y"] = GeoExtent( geosrs, -180.0, 84.0, 0.0, 90.0 ); _gzd["1Z"] = GeoExtent( geosrs, 0.0, 84.0, 180.0, 90.0 ); _gzd["1A"] = GeoExtent( geosrs, -180.0, -90.0, 0.0, -80.0 ); _gzd["1B"] = GeoExtent( geosrs, 0.0, -90.0, 180.0, -80.0 ); // replace the "exception" zones in Norway and Svalbard _gzd["31V"] = GeoExtent( geosrs, 0.0, 56.0, 3.0, 64.0 ); _gzd["32V"] = GeoExtent( geosrs, 3.0, 56.0, 12.0, 64.0 ); _gzd["31X"] = GeoExtent( geosrs, 0.0, 72.0, 9.0, 84.0 ); _gzd["33X"] = GeoExtent( geosrs, 9.0, 72.0, 21.0, 84.0 ); _gzd["35X"] = GeoExtent( geosrs, 21.0, 72.0, 33.0, 84.0 ); _gzd["37X"] = GeoExtent( geosrs, 33.0, 72.0, 42.0, 84.0 ); // ..and remove the non-existant zones: _gzd.erase( "32X" ); _gzd.erase( "34X" ); _gzd.erase( "36X" ); // now build the lateral tiles for the GZD level. for( SectorTable::iterator i = _gzd.begin(); i != _gzd.end(); ++i ) { osg::Node* tile = buildGZDTile( i->first, i->second ); if ( tile ) _root->addChild( tile ); } DepthOffsetUtils::prepareGraph( _root ); }
void MapNodeHelper::parse(MapNode* mapNode, osg::ArgumentParser& args, osgViewer::View* view, osg::Group* root, Container* userContainer ) const { if ( !root ) root = mapNode; // options to use for the load osg::ref_ptr<osgDB::Options> dbOptions = Registry::instance()->cloneOrCreateOptions(); // parse out custom example arguments first: bool useMGRS = args.read("--mgrs"); bool useDMS = args.read("--dms"); bool useDD = args.read("--dd"); bool useCoords = args.read("--coords") || useMGRS || useDMS || useDD; bool useAutoClip = args.read("--autoclip"); bool animateSky = args.read("--animate-sky"); bool showActivity = args.read("--activity"); bool useLogDepth = args.read("--logdepth"); bool useLogDepth2 = args.read("--logdepth2"); bool kmlUI = args.read("--kmlui"); if (args.read("--verbose")) osgEarth::setNotifyLevel(osg::INFO); if (args.read("--quiet")) osgEarth::setNotifyLevel(osg::FATAL); float ambientBrightness = 0.2f; args.read("--ambientBrightness", ambientBrightness); std::string kmlFile; args.read( "--kml", kmlFile ); std::string imageFolder; args.read( "--images", imageFolder ); std::string imageExtensions; args.read("--image-extensions", imageExtensions); // animation path: std::string animpath; if ( args.read("--path", animpath) ) { view->setCameraManipulator( new osgGA::AnimationPathManipulator(animpath) ); } // Install a new Canvas for our UI controls, or use one that already exists. ControlCanvas* canvas = ControlCanvas::getOrCreate( view ); Container* mainContainer; if ( userContainer ) { mainContainer = userContainer; } else { mainContainer = new VBox(); mainContainer->setAbsorbEvents( true ); mainContainer->setBackColor( Color(Color::Black, 0.8) ); mainContainer->setHorizAlign( Control::ALIGN_LEFT ); mainContainer->setVertAlign( Control::ALIGN_BOTTOM ); } canvas->addControl( mainContainer ); // Add an event handler to toggle the canvas with a key press; view->addEventHandler(new ToggleCanvasEventHandler(canvas) ); // look for external data in the map node: const Config& externals = mapNode->externalConfig(); //const Config& screenSpaceLayoutConf = // externals.hasChild("screen_space_layout") ? externals.child("screen_space_layout") : // externals.child("decluttering"); // backwards-compatibility // some terrain effects. // TODO: Most of these are likely to move into extensions. const Config& lodBlendingConf = externals.child("lod_blending"); const Config& vertScaleConf = externals.child("vertical_scale"); // Shadowing. if (args.read("--shadows")) { int unit; if ( mapNode->getTerrainEngine()->getResources()->reserveTextureImageUnit(unit, "ShadowCaster") ) { ShadowCaster* caster = new ShadowCaster(); caster->setTextureImageUnit( unit ); caster->setLight( view->getLight() ); caster->getShadowCastingGroup()->addChild( mapNode ); if ( mapNode->getNumParents() > 0 ) { insertGroup(caster, mapNode->getParent(0)); } else { caster->addChild(mapNode); root = caster; } } } // Loading KML from the command line: if ( !kmlFile.empty() ) { KMLOptions kml_options; kml_options.declutter() = true; // set up a default icon for point placemarks: IconSymbol* defaultIcon = new IconSymbol(); defaultIcon->url()->setLiteral(KML_PUSHPIN_URL); kml_options.defaultIconSymbol() = defaultIcon; TextSymbol* defaultText = new TextSymbol(); defaultText->halo() = Stroke(0.3,0.3,0.3,1.0); kml_options.defaultTextSymbol() = defaultText; osg::Node* kml = KML::load( URI(kmlFile), mapNode, kml_options ); if ( kml ) { if (kmlUI) { Control* c = AnnotationGraphControlFactory().create(kml, view); if ( c ) { c->setVertAlign( Control::ALIGN_TOP ); canvas->addControl( c ); } } root->addChild( kml ); } else { OE_NOTICE << "Failed to load " << kmlFile << std::endl; } } //// Configure the de-cluttering engine for labels and annotations: //if ( !screenSpaceLayoutConf.empty() ) //{ // ScreenSpaceLayout::setOptions( ScreenSpaceLayoutOptions(screenSpaceLayoutConf) ); //} // Configure the mouse coordinate readout: if ( useCoords ) { LabelControl* readout = new LabelControl(); readout->setBackColor( Color(Color::Black, 0.8) ); readout->setHorizAlign( Control::ALIGN_RIGHT ); readout->setVertAlign( Control::ALIGN_BOTTOM ); Formatter* formatter = useMGRS ? (Formatter*)new MGRSFormatter(MGRSFormatter::PRECISION_1M, 0L, MGRSFormatter::USE_SPACES) : useDMS ? (Formatter*)new LatLongFormatter(LatLongFormatter::FORMAT_DEGREES_MINUTES_SECONDS) : useDD ? (Formatter*)new LatLongFormatter(LatLongFormatter::FORMAT_DECIMAL_DEGREES) : 0L; MouseCoordsTool* mcTool = new MouseCoordsTool( mapNode ); mcTool->addCallback( new MouseCoordsLabelCallback(readout, formatter) ); view->addEventHandler( mcTool ); canvas->addControl( readout ); } // Configure for an ortho camera: if ( args.read("--ortho") ) { view->getCamera()->setProjectionMatrixAsOrtho(-1, 1, -1, 1, 0, 1); } // activity monitor (debugging) if ( showActivity ) { VBox* vbox = new VBox(); vbox->setBackColor( Color(Color::Black, 0.8) ); vbox->setHorizAlign( Control::ALIGN_RIGHT ); vbox->setVertAlign( Control::ALIGN_BOTTOM ); view->addEventHandler( new ActivityMonitorTool(vbox) ); canvas->addControl( vbox ); } // Install an auto clip plane clamper if ( useAutoClip ) { mapNode->addCullCallback( new AutoClipPlaneCullCallback(mapNode) ); } // Install logarithmic depth buffer on main camera if ( useLogDepth ) { OE_INFO << LC << "Activating logarithmic depth buffer (vertex-only) on main camera" << std::endl; osgEarth::Util::LogarithmicDepthBuffer logDepth; logDepth.setUseFragDepth( false ); logDepth.install( view->getCamera() ); } else if ( useLogDepth2 ) { OE_INFO << LC << "Activating logarithmic depth buffer (precise) on main camera" << std::endl; osgEarth::Util::LogarithmicDepthBuffer logDepth; logDepth.setUseFragDepth( true ); logDepth.install( view->getCamera() ); } // Scan for images if necessary. if ( !imageFolder.empty() ) { std::vector<std::string> extensions; if ( !imageExtensions.empty() ) StringTokenizer( imageExtensions, extensions, ",;", "", false, true ); if ( extensions.empty() ) extensions.push_back( "tif" ); OE_INFO << LC << "Loading images from " << imageFolder << "..." << std::endl; ImageLayerVector imageLayers; DataScanner scanner; scanner.findImageLayers( imageFolder, extensions, imageLayers ); if ( imageLayers.size() > 0 ) { mapNode->getMap()->beginUpdate(); for( ImageLayerVector::iterator i = imageLayers.begin(); i != imageLayers.end(); ++i ) { mapNode->getMap()->addImageLayer( i->get() ); } mapNode->getMap()->endUpdate(); } OE_INFO << LC << "...found " << imageLayers.size() << " image layers." << std::endl; } // Install elevation morphing if ( !lodBlendingConf.empty() ) { mapNode->getTerrainEngine()->addEffect( new LODBlending(lodBlendingConf) ); } // Install vertical scaler if ( !vertScaleConf.empty() ) { mapNode->getTerrainEngine()->addEffect( new VerticalScale(vertScaleConf) ); } // Install a contour map effect. if (args.read("--contourmap")) { mapNode->addExtension(Extension::create("contourmap", ConfigOptions())); // with the cmdline switch, hids all the image layer so we can see the contour map. for (unsigned i = 0; i < mapNode->getMap()->getNumImageLayers(); ++i) { mapNode->getMap()->getImageLayerAt(i)->setVisible(false); } } // Generic named value uniform with min/max. VBox* uniformBox = 0L; while( args.find( "--uniform" ) >= 0 ) { std::string name; float minval, maxval; if ( args.read( "--uniform", name, minval, maxval ) ) { if ( uniformBox == 0L ) { uniformBox = new VBox(); uniformBox->setBackColor(0,0,0,0.5); uniformBox->setAbsorbEvents( true ); canvas->addControl( uniformBox ); } osg::Uniform* uniform = new osg::Uniform(osg::Uniform::FLOAT, name); uniform->set( minval ); root->getOrCreateStateSet()->addUniform( uniform, osg::StateAttribute::OVERRIDE ); HBox* box = new HBox(); box->addControl( new LabelControl(name) ); HSliderControl* hs = box->addControl( new HSliderControl(minval, maxval, minval, new ApplyValueUniform(uniform))); hs->setHorizFill(true, 200); box->addControl( new LabelControl(hs) ); uniformBox->addControl( box ); OE_INFO << LC << "Installed uniform controller for " << name << std::endl; } } // Map inspector: if (args.read("--inspect")) { mapNode->addExtension( Extension::create("mapinspector", ConfigOptions()) ); } // Memory monitor: if (args.read("--monitor")) { mapNode->addExtension(Extension::create("monitor", ConfigOptions()) ); } // Simple sky model: if (args.read("--sky")) { mapNode->addExtension(Extension::create("sky_simple", ConfigOptions()) ); } // Simple ocean model: if (args.read("--ocean")) { mapNode->addExtension(Extension::create("ocean_simple", ConfigOptions())); } // Hook up the extensions! for(std::vector<osg::ref_ptr<Extension> >::const_iterator eiter = mapNode->getExtensions().begin(); eiter != mapNode->getExtensions().end(); ++eiter) { Extension* e = eiter->get(); // Check for a View interface: ExtensionInterface<osg::View>* viewIF = ExtensionInterface<osg::View>::get( e ); if ( viewIF ) viewIF->connect( view ); // Check for a Control interface: ExtensionInterface<Control>* controlIF = ExtensionInterface<Control>::get( e ); if ( controlIF ) controlIF->connect( mainContainer ); } root->addChild( canvas ); }
bool SLDReader::readStyleFromCSSParams( const Config& conf, Style& sc ) { sc.setName( conf.key() ); LineSymbol* line = 0L; PolygonSymbol* polygon = 0L; PointSymbol* point = 0L; TextSymbol* text = 0L; ExtrusionSymbol* extrusion = 0L; MarkerSymbol* marker = 0L; AltitudeSymbol* altitude = 0L; for(Properties::const_iterator p = conf.attrs().begin(); p != conf.attrs().end(); p++ ) { if ( p->first == CSS_STROKE ) { if (!line) line = sc.getOrCreateSymbol<LineSymbol>(); line->stroke()->color() = htmlColorToVec4f( p->second ); } else if ( p->first == CSS_STROKE_OPACITY ) { if (!line) line = sc.getOrCreateSymbol<LineSymbol>(); line->stroke()->color().a() = as<float>( p->second, 1.0f ); } else if ( p->first == CSS_STROKE_WIDTH ) { if (!line) line = sc.getOrCreateSymbol<LineSymbol>(); line->stroke()->width() = as<float>( p->second, 1.0f ); } else if ( p->first == CSS_STROKE_LINECAP ) { if (!line) line = sc.getOrCreateSymbol<LineSymbol>(); parseLineCap( p->second, line->stroke()->lineCap() ); } else if ( p->first == CSS_FILL ) { if (!polygon) polygon = sc.getOrCreateSymbol<PolygonSymbol>(); polygon->fill()->color() = htmlColorToVec4f( p->second ); if ( !point ) point = sc.getOrCreateSymbol<PointSymbol>(); point->fill()->color() = htmlColorToVec4f( p->second ); if ( !text ) text = new TextSymbol(); text->fill()->color() = htmlColorToVec4f( p->second ); } else if ( p->first == CSS_FILL_OPACITY ) { if (!polygon) polygon = sc.getOrCreateSymbol<PolygonSymbol>(); polygon->fill()->color().a() = as<float>( p->second, 1.0f ); if (!polygon) polygon = sc.getOrCreateSymbol<PolygonSymbol>(); point->fill()->color().a() = as<float>( p->second, 1.0f ); if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); text->fill()->color().a() = as<float>( p->second, 1.0f ); } else if (p->first == CSS_POINT_SIZE) { if ( !point ) point = sc.getOrCreateSymbol<PointSymbol>(); point->size() = as<float>(p->second, 1.0f); } else if (p->first == CSS_TEXT_SIZE) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); text->size() = as<float>(p->second, 32.0f); } else if (p->first == CSS_TEXT_FONT) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); text->font() = p->second; } else if (p->first == CSS_TEXT_HALO) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); text->halo()->color() = htmlColorToVec4f( p->second ); } //else if (p->first == CSS_TEXT_ATTRIBUTE) //{ // if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); // text->attribute() = p->second; //} else if (p->first == CSS_TEXT_ROTATE_TO_SCREEN) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); if (p->second == "true") text->rotateToScreen() = true; else if (p->second == "false") text->rotateToScreen() = false; } else if (p->first == CSS_TEXT_SIZE_MODE) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); if (p->second == "screen") text->sizeMode() = TextSymbol::SIZEMODE_SCREEN; else if (p->second == "object") text->sizeMode() = TextSymbol::SIZEMODE_OBJECT; } else if (p->first == CSS_TEXT_REMOVE_DUPLICATE_LABELS) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); if (p->second == "true") text->removeDuplicateLabels() = true; else if (p->second == "false") text->removeDuplicateLabels() = false; } else if (p->first == CSS_TEXT_LINE_ORIENTATION) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); if (p->second == "parallel") text->lineOrientation() = TextSymbol::LINEORIENTATION_PARALLEL; else if (p->second == "horizontal") text->lineOrientation() = TextSymbol::LINEORIENTATION_HORIZONTAL; else if (p->second == "perpendicular") text->lineOrientation() = TextSymbol::LINEORIENTATION_PERPENDICULAR; } else if (p->first == CSS_TEXT_LINE_PLACEMENT) { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); if (p->second == "centroid") text->linePlacement() = TextSymbol::LINEPLACEMENT_CENTROID; else if (p->second == "along-line") text->linePlacement() = TextSymbol::LINEPLACEMENT_ALONG_LINE; } else if (p->first == "text-content") { if (!text) text = sc.getOrCreate<TextSymbol>(); text->content() = StringExpression( p->second ); } else if (p->first == "text-priority") { if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); text->priority() = NumericExpression( p->second ); } else if (p->first == "text-provider") { if (!text) text = sc.getOrCreate<TextSymbol>(); text->provider() = p->second; } //else if (p->first == CSS_TEXT_CONTENT) //{ // if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); // text->content() = p->second; //} //else if (p->first == CSS_TEXT_CONTENT_ATTRIBUTE_DELIMITER) //{ // if (!text) text = sc.getOrCreateSymbol<TextSymbol>(); // text->contentAttributeDelimiter() = p->second; //} else if (p->first == "marker") { if (!marker) marker = sc.getOrCreateSymbol<MarkerSymbol>(); marker->url() = p->second; } else if (p->first == "marker-placement") { if (!marker) marker = sc.getOrCreateSymbol<MarkerSymbol>(); if (p->second == "centroid") marker->placement() = MarkerSymbol::PLACEMENT_CENTROID; else if (p->second == "interval") marker->placement() = MarkerSymbol::PLACEMENT_INTERVAL; else if (p->second == "random" ) marker->placement() = MarkerSymbol::PLACEMENT_RANDOM; } else if (p->first == "marker-density") { if (!marker) marker = sc.getOrCreateSymbol<MarkerSymbol>(); marker->density() = as<float>(p->second, 1.0f); } else if (p->first == "marker-random-seed") { if (!marker) marker = sc.getOrCreateSymbol<MarkerSymbol>(); marker->randomSeed() = as<unsigned>(p->second, 0); } else if (p->first == "marker-scale") { if (!marker) marker = sc.getOrCreateSymbol<MarkerSymbol>(); marker->scale() = stringToVec3f(p->second, osg::Vec3f(1,1,1)); } else if (p->first == "extrusion-height") { if (!extrusion) extrusion = sc.getOrCreateSymbol<ExtrusionSymbol>(); extrusion->heightExpression() = NumericExpression(p->second); } else if (p->first == "extrusion-flatten") { if (!extrusion) extrusion = sc.getOrCreateSymbol<ExtrusionSymbol>(); extrusion->flatten() = as<bool>(p->second, true); } else if (p->first == "altitude-clamping") { if (!altitude) altitude = sc.getOrCreateSymbol<AltitudeSymbol>(); if (p->second == "none" ) altitude->clamping() = AltitudeSymbol::CLAMP_NONE; else if (p->second == "terrain" ) altitude->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; else if (p->second == "relative") altitude->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN; } else if (p->first == "altitude-offset") { if (!altitude) altitude = sc.getOrCreateSymbol<AltitudeSymbol>(); altitude->verticalOffset() = as<float>( p->second, 0.0f ); } } #if 0 if (line) sc.addSymbol(line); if (polygon) sc.addSymbol(polygon); if (point) sc.addSymbol(point); if (text) sc.addSymbol(text); if (extrusion) sc.addSymbol(extrusion); if (marker) sc.addSymbol(marker); if (altitude) sc.addSymbol(altitude); #endif return true; }
void MapInspectorUI::addTerrainLayer(TerrainLayer* layer, MapNode* mapNode) { const Color colors[6] = { Color::White, Color::Yellow, Color::Cyan, Color::Lime, Color::Red, Color::Magenta }; Color color = colors[(int)layer->getUID()%6]; osg::ref_ptr<MultiGeometry> collection = new MultiGeometry(); const DataExtentList& exlist = layer->getDataExtents(); if (!exlist.empty()) { for(DataExtentList::const_iterator i = exlist.begin(); i != exlist.end(); ++i) { const DataExtent& e = *i; Polygon* p = new Polygon(); p->push_back( e.xMin(), e.yMin() ); p->push_back( e.xMax(), e.yMin() ); p->push_back( e.xMax(), e.yMax() ); p->push_back( e.xMin(), e.yMax() ); collection->add( p ); } // poly: { Style style; style.getOrCreate<LineSymbol>()->stroke()->color() = color; style.getOrCreate<LineSymbol>()->stroke()->width() = 2; style.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; style.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_DRAPE; style.getOrCreate<RenderSymbol>()->lighting() = false; Feature* feature = new Feature(collection.get(), layer->getProfile()->getSRS(), style); FeatureNode* node = new FeatureNode( mapNode, feature ); _annos->addChild( node ); } // label: std::string text = !layer->getName().empty()? layer->getName() : Stringify() << "Layer " << layer->getUID(); { Style style; TextSymbol* ts = style.getOrCreate<TextSymbol>(); ts->halo()->color().set(0,0,0,1); ts->declutter() = true; ts->alignment() = TextSymbol::ALIGN_CENTER_CENTER; osg::Vec2d center = collection->getBounds().center2d(); GeoPoint position(layer->getProfile()->getSRS(), center.x(), center.y(), 0.0, ALTMODE_ABSOLUTE); LabelNode* label = new LabelNode(mapNode, position, text, style); _annos->addChild( label ); } unsigned r = this->getNumRows(); setControl(0, r, new ui::LabelControl(text, color)); } }
// // NOTE: run this sample from the repo/tests directory. // int main(int argc, char** argv) { osg::ArgumentParser arguments(&argc,argv); bool useRaster = arguments.read("--rasterize"); bool useOverlay = arguments.read("--overlay"); bool useStencil = arguments.read("--stencil"); bool useMem = arguments.read("--mem"); bool useLabels = arguments.read("--labels"); osgViewer::Viewer viewer(arguments); // Start by creating the map: Map* map = new Map(); // Start with a basemap imagery layer; we'll be using the GDAL driver // to load a local GeoTIFF file: GDALOptions basemapOpt; basemapOpt.url() = "../data/world.tif"; map->addImageLayer( new ImageLayer( ImageLayerOptions("basemap", basemapOpt) ) ); // Next we add a feature layer. First configure a feature driver to // load the vectors from a shapefile: OGRFeatureOptions featureOpt; if ( !useMem ) { featureOpt.url() = "../data/usa.shp"; } else { Ring* line = new Ring(); line->push_back( osg::Vec3d(-60, 20, 0) ); line->push_back( osg::Vec3d(-120, 20, 0) ); line->push_back( osg::Vec3d(-120, 60, 0) ); line->push_back( osg::Vec3d(-60, 60, 0) ); featureOpt.geometry() = line; } // Define a style for the feature data. Since we are going to render the // vectors as lines, configure the line symbolizer: Style style; LineSymbol* ls = style.getOrCreateSymbol<LineSymbol>(); ls->stroke()->color() = osg::Vec4f( 1,1,0,1 ); // yellow ls->stroke()->width() = 2.0f; // Add some text labels. if ( useLabels ) { TextSymbol* text = style.getOrCreateSymbol<TextSymbol>(); text->provider() = "overlay"; text->content() = StringExpression( "[name]" ); text->priority() = NumericExpression( "[area]" ); text->removeDuplicateLabels() = true; text->size() = 16.0f; text->fill()->color() = Color::White; text->halo()->color() = Color::DarkGray; } // That's it, the map is ready; now create a MapNode to render the Map: MapNodeOptions mapNodeOptions; mapNodeOptions.enableLighting() = false; MapNode* mapNode = new MapNode( map, mapNodeOptions ); // Now we'll choose the AGG-Lite driver to render the features. By the way, the // feature data is actually polygons, so we override that to treat it as lines. // We apply the feature driver and set the style as well. if (useStencil) { FeatureStencilModelOptions worldOpt; worldOpt.featureOptions() = featureOpt; worldOpt.geometryTypeOverride() = Geometry::TYPE_LINESTRING; worldOpt.styles() = new StyleSheet(); worldOpt.styles()->addStyle( style ); worldOpt.enableLighting() = false; worldOpt.depthTestEnabled() = false; map->addModelLayer( new ModelLayer( "my features", worldOpt ) ); } else if (useRaster) { AGGLiteOptions worldOpt; worldOpt.featureOptions() = featureOpt; worldOpt.geometryTypeOverride() = Geometry::TYPE_LINESTRING; worldOpt.styles() = new StyleSheet(); worldOpt.styles()->addStyle( style ); map->addImageLayer( new ImageLayer( ImageLayerOptions("world", worldOpt) ) ); } else //if (useGeom || useOverlay) { FeatureGeomModelOptions worldOpt; worldOpt.featureOptions() = featureOpt; worldOpt.geometryTypeOverride() = Geometry::TYPE_LINESTRING; worldOpt.styles() = new StyleSheet(); worldOpt.styles()->addStyle( style ); worldOpt.enableLighting() = false; worldOpt.depthTestEnabled() = false; ModelLayerOptions options( "my features", worldOpt ); options.overlay() = useOverlay; map->addModelLayer( new ModelLayer(options) ); } viewer.setSceneData( mapNode ); viewer.setCameraManipulator( new EarthManipulator() ); if ( !useStencil && !useOverlay ) viewer.addEventHandler( new osgEarth::Util::AutoClipPlaneHandler ); // add some stock OSG handlers: viewer.addEventHandler(new osgViewer::StatsHandler()); viewer.addEventHandler(new osgViewer::WindowSizeHandler()); viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())); return viewer.run(); }
void KML_Placemark::build( const Config& conf, KMLContext& cx ) { Style masterStyle; if ( conf.hasValue("styleurl") ) { // process a "stylesheet" style const Style* ref_style = cx._sheet->getStyle( conf.value("styleurl"), false ); if ( ref_style ) masterStyle = *ref_style; } else if ( conf.hasChild("style") ) { // process an "inline" style KML_Style kmlStyle; kmlStyle.scan( conf.child("style"), cx ); masterStyle = cx._activeStyle; } // parse the geometry. the placemark must have geometry to be valid. The // geometry parse may optionally specify an altitude mode as well. KML_Geometry geometry; geometry.build(conf, cx, masterStyle); Geometry* allGeom = geometry._geom.get(); if ( allGeom ) { GeometryIterator giter( allGeom, false ); while( giter.hasMore() ) { Geometry* geom = giter.next(); Style style = masterStyle; // KML's default altitude mode is clampToGround. AltitudeMode altMode = ALTMODE_RELATIVE; AltitudeSymbol* altSym = style.get<AltitudeSymbol>(); if ( !altSym ) { altSym = style.getOrCreate<AltitudeSymbol>(); altSym->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN; altSym->technique() = AltitudeSymbol::TECHNIQUE_SCENE; } else if ( !altSym->clamping().isSetTo(AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN) ) { altMode = ALTMODE_ABSOLUTE; } if ( geom && geom->getTotalPointCount() > 0 ) { GeoPoint position(cx._srs.get(), geom->getBounds().center(), altMode); bool isPoly = geom->getComponentType() == Geometry::TYPE_POLYGON; bool isPoint = geom->getComponentType() == Geometry::TYPE_POINTSET; // check for symbols. ModelSymbol* model = style.get<ModelSymbol>(); IconSymbol* icon = style.get<IconSymbol>(); TextSymbol* text = style.get<TextSymbol>(); if ( !text && cx._options->defaultTextSymbol().valid() ) text = cx._options->defaultTextSymbol().get(); // the annotation name: std::string name = conf.hasValue("name") ? conf.value("name") : ""; if ( text && !name.empty() ) { text->content()->setLiteral( name ); } AnnotationNode* featureNode = 0L; AnnotationNode* iconNode = 0L; AnnotationNode* modelNode = 0L; // one coordinate? It's a place marker or a label. if ( model || icon || text || geom->getTotalPointCount() == 1 ) { // load up the default icon if there we don't have one. if ( !model && !icon ) { icon = cx._options->defaultIconSymbol().get(); if ( icon ) style.add( icon ); } // if there's a model, render that - models do NOT get labels. if ( model ) { ModelNode* node = new ModelNode( cx._mapNode, style, cx._dbOptions ); node->setPosition( position ); if ( cx._options->modelScale() != 1.0f ) { float s = *cx._options->modelScale(); node->setScale( osg::Vec3f(s,s,s) ); } if ( !cx._options->modelRotation()->zeroRotation() ) { node->setLocalRotation( *cx._options->modelRotation() ); } modelNode = node; } else if ( !text && !name.empty() ) { text = style.getOrCreate<TextSymbol>(); text->content()->setLiteral( name ); } if ( icon ) { iconNode = new PlaceNode( cx._mapNode, position, style, cx._dbOptions ); } else if ( !model && text && !name.empty() ) { // note: models do not get labels. iconNode = new LabelNode( cx._mapNode, position, style ); } } // multiple coords? feature: if ( geom->getTotalPointCount() > 1 ) { ExtrusionSymbol* extruded = style.get<ExtrusionSymbol>(); AltitudeSymbol* altitude = style.get<AltitudeSymbol>(); // Remove symbols that we have already processed so the geometry // compiler doesn't get confused. if ( model ) style.removeSymbol( model ); if ( icon ) style.removeSymbol( icon ); if ( text ) style.removeSymbol( text ); // analyze the data; if the Z coords are all 0.0, enable draping. if ( /*isPoly &&*/ !extruded && altitude && altitude->clamping() != AltitudeSymbol::CLAMP_TO_TERRAIN ) { bool zeroElev = true; ConstGeometryIterator gi( geom, false ); while( zeroElev == true && gi.hasMore() ) { const Geometry* g = gi.next(); for( Geometry::const_iterator ji = g->begin(); ji != g->end() && zeroElev == true; ++ji ) { if ( !osg::equivalent(ji->z(), 0.0) ) zeroElev = false; } } if ( zeroElev ) { altitude->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN; altitude->technique() = AltitudeSymbol::TECHNIQUE_GPU; } } // Make a feature node; drape if we're not extruding. bool draped = isPoly && !extruded && (!altitude || altitude->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN); if ( draped && style.get<LineSymbol>() && !style.get<PolygonSymbol>() ) { draped = false; } // turn off the clamping if we're draping. if ( draped && altitude ) { altitude->technique() = AltitudeSymbol::TECHNIQUE_DRAPE; } GeometryCompilerOptions compilerOptions; // Check for point-model substitution: if ( style.has<ModelSymbol>() ) { compilerOptions.instancing() = true; } Feature* feature = new Feature(geom, cx._srs.get(), style); featureNode = new FeatureNode( cx._mapNode, feature, draped, compilerOptions ); } // assemble the results: if ( (iconNode || modelNode) && featureNode ) { osg::Group* group = new osg::Group(); group->addChild( featureNode ); if ( iconNode ) group->addChild( iconNode ); if ( modelNode ) group->addChild( modelNode ); cx._groupStack.top()->addChild( group ); if ( iconNode && cx._options->declutter() == true ) Decluttering::setEnabled( iconNode->getOrCreateStateSet(), true ); if ( iconNode ) KML_Feature::build( conf, cx, iconNode ); if ( modelNode ) KML_Feature::build( conf, cx, modelNode ); if ( featureNode ) KML_Feature::build( conf, cx, featureNode ); } else { if ( iconNode ) { if ( cx._options->iconAndLabelGroup().valid() ) { cx._options->iconAndLabelGroup()->addChild( iconNode ); } else { cx._groupStack.top()->addChild( iconNode ); if ( cx._options->declutter() == true ) Decluttering::setEnabled( iconNode->getOrCreateStateSet(), true ); } KML_Feature::build( conf, cx, iconNode ); } if ( modelNode ) { cx._groupStack.top()->addChild( modelNode ); KML_Feature::build( conf, cx, modelNode ); } if ( featureNode ) { cx._groupStack.top()->addChild( featureNode ); KML_Feature::build( conf, cx, featureNode ); } } } } } }
void PlaceNode::init() { Decluttering::setEnabled( this->getOrCreateStateSet(), true ); //reset. //this->clearDecoration(); getPositionAttitudeTransform()->removeChildren(0, getPositionAttitudeTransform()->getNumChildren()); _geode = new osg::Geode(); // ensure that (0,0,0) is the bounding sphere control/center point. // useful for things like horizon culling. _geode->setComputeBoundingSphereCallback(new ControlPointCallback()); osg::Drawable* text = 0L; // If there's no explicit text, look to the text symbol for content. if ( _text.empty() && _style.has<TextSymbol>() ) { _text = _style.get<TextSymbol>()->content()->eval(); } osg::ref_ptr<const InstanceSymbol> instance = _style.get<InstanceSymbol>(); // backwards compability, support for deprecated MarkerSymbol if ( !instance.valid() && _style.has<MarkerSymbol>() ) { instance = _style.get<MarkerSymbol>()->convertToInstanceSymbol(); } const IconSymbol* icon = instance->asIcon(); if ( !_image.valid() ) { URI imageURI; if ( icon ) { if ( icon->url().isSet() ) { imageURI = icon->url()->evalURI(); } else if (icon->getImage()) { _image = icon->getImage(); } } if ( !imageURI.empty() ) { _image = imageURI.getImage( _dbOptions.get() ); } } osg::BoundingBox imageBox(0,0,0,0,0,0); // found an image; now format it: if ( _image.get() ) { // Scale the icon if necessary double scale = 1.0; if ( icon && icon->scale().isSet() ) { scale = icon->scale()->eval(); } double s = scale * _image->s(); double t = scale * _image->t(); // this offset anchors the image at the bottom osg::Vec2s offset; if ( !icon || !icon->alignment().isSet() ) { // default to bottom center offset.set(0.0, t / 2.0); } else { // default to bottom center switch (icon->alignment().value()) { case IconSymbol::ALIGN_LEFT_TOP: offset.set((s / 2.0), -(t / 2.0)); break; case IconSymbol::ALIGN_LEFT_CENTER: offset.set((s / 2.0), 0.0); break; case IconSymbol::ALIGN_LEFT_BOTTOM: offset.set((s / 2.0), (t / 2.0)); break; case IconSymbol::ALIGN_CENTER_TOP: offset.set(0.0, -(t / 2.0)); break; case IconSymbol::ALIGN_CENTER_CENTER: offset.set(0.0, 0.0); break; case IconSymbol::ALIGN_CENTER_BOTTOM: default: offset.set(0.0, (t / 2.0)); break; case IconSymbol::ALIGN_RIGHT_TOP: offset.set(-(s / 2.0), -(t / 2.0)); break; case IconSymbol::ALIGN_RIGHT_CENTER: offset.set(-(s / 2.0), 0.0); break; case IconSymbol::ALIGN_RIGHT_BOTTOM: offset.set(-(s / 2.0), (t / 2.0)); break; } } // Apply a rotation to the marker if requested: double heading = 0.0; if ( icon && icon->heading().isSet() ) { heading = osg::DegreesToRadians( icon->heading()->eval() ); } //We must actually rotate the geometry itself and not use a MatrixTransform b/c the //decluttering doesn't respect Transforms above the drawable. osg::Geometry* imageGeom = AnnotationUtils::createImageGeometry( _image.get(), offset, 0, heading, scale ); if ( imageGeom ) { _geode->addDrawable( imageGeom ); imageBox = imageGeom->getBoundingBox(); } } if ( _image.valid() ) { TextSymbol* textSymbol = _style.getOrCreate<TextSymbol>(); if ( !textSymbol->alignment().isSet() ) textSymbol->alignment() = textSymbol->ALIGN_LEFT_CENTER; } text = AnnotationUtils::createTextDrawable( _text, _style.get<TextSymbol>(), imageBox ); if ( text ) _geode->addDrawable( text ); osg::StateSet* stateSet = _geode->getOrCreateStateSet(); stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 ); getPositionAttitudeTransform()->addChild( _geode ); // for clamping and occlusion culling //OE_WARN << LC << "PlaceNode::applyStyle: " << _style.getConfig().toJSON(true) << std::endl; applyStyle( _style ); setLightingIfNotSet( false ); // generate shaders: Registry::shaderGenerator().run( this, "osgEarth.PlaceNode", Registry::stateSetCache() ); setPriority(getPriority()); if ( _dynamic ) setDynamic( _dynamic ); }
osg::Node* MGRSGraticule::buildSQIDTiles( const std::string& gzd ) { const GeoExtent& extent = _gzd[gzd]; // parse the GZD into its components: unsigned zone; char letter; sscanf( gzd.c_str(), "%u%c", &zone, &letter ); TextSymbol* textSym = _options->secondaryStyle()->get<TextSymbol>(); if ( !textSym ) textSym = _options->primaryStyle()->getOrCreate<TextSymbol>(); AltitudeSymbol* alt = _options->secondaryStyle()->get<AltitudeSymbol>(); double h = 0.0; TextSymbolizer ts( textSym ); MGRSFormatter mgrs(MGRSFormatter::PRECISION_100000M); osg::Geode* textGeode = new osg::Geode(); textGeode->getOrCreateStateSet()->setRenderBinDetails( 9999, "DepthSortedBin" ); textGeode->getOrCreateStateSet()->setAttributeAndModes( _depthAttribute, 1 ); const SpatialReference* ecefSRS = extent.getSRS()->getECEF(); osg::Vec3d centerMap, centerECEF; extent.getCentroid(centerMap.x(), centerMap.y()); extent.getSRS()->transform(centerMap, ecefSRS, centerECEF); //extent.getSRS()->transformToECEF(centerMap, centerECEF); osg::Matrix local2world; ecefSRS->createLocalToWorld( centerECEF, local2world ); //= ECEF::createLocalToWorld(centerECEF); osg::Matrix world2local; world2local.invert(local2world); FeatureList features; std::vector<GeoExtent> sqidExtents; // UTM: if ( letter > 'B' && letter < 'Y' ) { // grab the SRS for the current UTM zone: // TODO: AL/AA designation?? const SpatialReference* utm = SpatialReference::create( Stringify() << "+proj=utm +zone=" << zone << " +north +units=m" ); // transform the four corners of the tile to UTM. osg::Vec3d gzdUtmSW, gzdUtmSE, gzdUtmNW, gzdUtmNE; extent.getSRS()->transform( osg::Vec3d(extent.xMin(),extent.yMin(),h), utm, gzdUtmSW ); extent.getSRS()->transform( osg::Vec3d(extent.xMin(),extent.yMax(),h), utm, gzdUtmNW ); extent.getSRS()->transform( osg::Vec3d(extent.xMax(),extent.yMin(),h), utm, gzdUtmSE ); extent.getSRS()->transform( osg::Vec3d(extent.xMax(),extent.yMax(),h), utm, gzdUtmNE ); // find the southern boundary of the first full SQID tile in the GZD tile. double southSQIDBoundary = gzdUtmSW.y(); //extentUTM.yMin(); double remainder = fmod( southSQIDBoundary, 100000.0 ); if ( remainder > 0.0 ) southSQIDBoundary += (100000.0 - remainder); // find the min/max X for this cell in UTM: double xmin = extent.yMin() >= 0.0 ? gzdUtmSW.x() : gzdUtmNW.x(); double xmax = extent.yMin() >= 0.0 ? gzdUtmSE.x() : gzdUtmNE.x(); // Record the UTM extent of each SQID cell in this tile. // Go from the south boundary northwards: for( double y = southSQIDBoundary; y < gzdUtmNW.y(); y += 100000.0 ) { // start at the central meridian (500K) and go west: for( double x = 500000.0; x > xmin; x -= 100000.0 ) { sqidExtents.push_back( GeoExtent(utm, x-100000.0, y, x, y+100000.0) ); } // then start at the central meridian and go east: for( double x = 500000.0; x < xmax; x += 100000.0 ) { sqidExtents.push_back( GeoExtent(utm, x, y, x+100000.0, y+100000.0) ); } } for( std::vector<GeoExtent>::iterator i = sqidExtents.begin(); i != sqidExtents.end(); ++i ) { GeoExtent utmEx = *i; // now, clamp each of the points in the UTM SQID extent to the map-space // boundaries of the GZD tile. (We only need to clamp in the X dimension, // Y geometry is allowed to overflow.) Also, skip NE, we don't need it. double r, xlimit; osg::Vec3d sw(utmEx.xMin(), utmEx.yMin(), 0); r = (sw.y()-gzdUtmSW.y())/(gzdUtmNW.y()-gzdUtmSW.y()); xlimit = gzdUtmSW.x() + r * (gzdUtmNW.x() - gzdUtmSW.x()); if ( sw.x() < xlimit ) sw.x() = xlimit; osg::Vec3d nw(utmEx.xMin(), utmEx.yMax(), 0); r = (nw.y()-gzdUtmSW.y())/(gzdUtmNW.y()-gzdUtmSW.y()); xlimit = gzdUtmSW.x() + r * (gzdUtmNW.x() - gzdUtmSW.x()); if ( nw.x() < xlimit ) nw.x() = xlimit; osg::Vec3d se(utmEx.xMax(), utmEx.yMin(), 0); r = (se.y()-gzdUtmSE.y())/(gzdUtmNE.y()-gzdUtmSE.y()); xlimit = gzdUtmSE.x() + r * (gzdUtmNE.x() - gzdUtmSE.x()); if ( se.x() > xlimit ) se.x() = xlimit; // at the northernmost GZD (lateral band X), clamp the northernmost SQIDs to the upper latitude. if ( letter == 'X' && nw.y() > gzdUtmNW.y() ) nw.y() = gzdUtmNW.y(); // need this in order to calculate the font size: double utmWidth = se.x() - sw.x(); // now transform the corner points back into the map SRS: utm->transform( sw, extent.getSRS(), sw ); utm->transform( nw, extent.getSRS(), nw ); utm->transform( se, extent.getSRS(), se ); // and draw valid sqid geometry. if ( sw.x() < se.x() ) { Feature* lat = new Feature(new LineString(2), extent.getSRS()); lat->geoInterp() = GEOINTERP_RHUMB_LINE; lat->getGeometry()->push_back( sw ); lat->getGeometry()->push_back( se ); features.push_back(lat); Feature* lon = new Feature(new LineString(2), extent.getSRS()); lon->geoInterp() = GEOINTERP_GREAT_CIRCLE; lon->getGeometry()->push_back( sw ); lon->getGeometry()->push_back( nw ); features.push_back(lon); // and the text label: osg::Vec3d sqidTextMap = (nw + se) * 0.5; sqidTextMap.z() += 1000.0; osg::Vec3d sqidTextECEF; extent.getSRS()->transform(sqidTextMap, ecefSRS, sqidTextECEF); //extent.getSRS()->transformToECEF(sqidTextMap, sqidTextECEF); osg::Vec3d sqidLocal; sqidLocal = sqidTextECEF * world2local; MGRSCoord mgrsCoord; if ( mgrs.transform( GeoPoint(extent.getSRS(),sqidTextMap,ALTMODE_ABSOLUTE), mgrsCoord) ) { textSym->size() = utmWidth/3.0; osgText::Text* d = ts.create( mgrsCoord.sqid ); osg::Matrixd textLocal2World; ecefSRS->createLocalToWorld( sqidTextECEF, textLocal2World ); d->setPosition( sqidLocal ); textGeode->addDrawable( d ); } } } } else if ( letter == 'A' || letter == 'B' ) { // SRS for south polar region UPS projection. This projection has (0,0) at the // south pole, with +X extending towards 90 degrees E longitude and +Y towards // 0 degrees longitude. const SpatialReference* ups = SpatialReference::create( "+proj=stere +lat_ts=-90 +lat_0=-90 +lon_0=0 +k_0=1 +x_0=0 +y_0=0"); osg::Vec3d gtemp; double r = GeoMath::distance(-osg::PI_2, 0.0, -1.3962634, 0.0); // -90 => -80 latitude double r2 = r*r; if ( letter == 'A' ) { for( double x = 0.0; x < 1200000.0; x += 100000.0 ) { double yminmax = sqrt( r2 - x*x ); Feature* f = new Feature( new LineString(2), extent.getSRS() ); f->geoInterp() = GEOINTERP_GREAT_CIRCLE; osg::Vec3d p0, p1; ups->transform( osg::Vec3d(-x, -yminmax, 0), extent.getSRS(), p0 ); ups->transform( osg::Vec3d(-x, yminmax, 0), extent.getSRS(), p1 ); f->getGeometry()->push_back( p0 ); f->getGeometry()->push_back( p1 ); features.push_back( f ); } for( double y = -1100000.0; y < 1200000.0; y += 100000.0 ) { double xmax = sqrt( r2 - y*y ); Feature* f = new Feature( new LineString(2), extent.getSRS() ); f->geoInterp() = GEOINTERP_GREAT_CIRCLE; osg::Vec3d p0, p1; ups->transform( osg::Vec3d(-xmax, y, 0), extent.getSRS(), p0 ); ups->transform( osg::Vec3d( 0, y, 0), extent.getSRS(), p1 ); f->getGeometry()->push_back( p0 ); f->getGeometry()->push_back( p1 ); features.push_back( f ); } for( double x = -1200000.0; x < 0.0; x += 100000.0 ) { for( double y = -1200000.0; y < 1200000.0; y += 100000.0 ) { osg::Vec3d sqidTextMap; ups->transform( osg::Vec3d(x+50000.0, y+50000.0, 0), extent.getSRS(), sqidTextMap); if ( sqidTextMap.y() < -80.0 ) { sqidTextMap.z() += 1000.0; osg::Vec3d sqidTextECEF; extent.getSRS()->transform(sqidTextMap, ecefSRS, sqidTextECEF); //extent.getSRS()->transformToECEF(sqidTextMap, sqidTextECEF); osg::Vec3d sqidLocal = sqidTextECEF * world2local; MGRSCoord mgrsCoord; if ( mgrs.transform( GeoPoint(extent.getSRS(),sqidTextMap,ALTMODE_ABSOLUTE), mgrsCoord) ) { textSym->size() = 33000.0; osgText::Text* d = ts.create( mgrsCoord.sqid ); osg::Matrixd textLocal2World; ecefSRS->createLocalToWorld( sqidTextECEF, textLocal2World ); d->setPosition( sqidLocal ); textGeode->addDrawable( d ); } } } } } else if ( letter == 'B' ) { for( double x = 100000.0; x < 1200000.0; x += 100000.0 ) { double yminmax = sqrt( r2 - x*x ); Feature* f = new Feature( new LineString(2), extent.getSRS() ); f->geoInterp() = GEOINTERP_GREAT_CIRCLE; osg::Vec3d p0, p1; ups->transform( osg::Vec3d(x, -yminmax, 0), extent.getSRS(), p0 ); ups->transform( osg::Vec3d(x, yminmax, 0), extent.getSRS(), p1 ); f->getGeometry()->push_back( p0 ); f->getGeometry()->push_back( p1 ); features.push_back( f ); } for( double y = -1100000.0; y < 1200000.0; y += 100000.0 ) { double xmax = sqrt( r2 - y*y ); Feature* f = new Feature( new LineString(2), extent.getSRS() ); f->geoInterp() = GEOINTERP_GREAT_CIRCLE; osg::Vec3d p0, p1; ups->transform( osg::Vec3d( 0, y, 0), extent.getSRS(), p0 ); ups->transform( osg::Vec3d( xmax, y, 0), extent.getSRS(), p1 ); f->getGeometry()->push_back( p0 ); f->getGeometry()->push_back( p1 ); features.push_back( f ); } for( double x = 0.0; x < 1200000.0; x += 100000.0 ) { for( double y = -1200000.0; y < 1200000.0; y += 100000.0 ) { osg::Vec3d sqidTextMap; ups->transform( osg::Vec3d(x+50000.0, y+50000.0, 0), extent.getSRS(), sqidTextMap); if ( sqidTextMap.y() < -80.0 ) { sqidTextMap.z() += 1000.0; osg::Vec3d sqidTextECEF; extent.getSRS()->transform(sqidTextMap, ecefSRS, sqidTextECEF); //extent.getSRS()->transformToECEF(sqidTextMap, sqidTextECEF); osg::Vec3d sqidLocal = sqidTextECEF * world2local; MGRSCoord mgrsCoord; if ( mgrs.transform( GeoPoint(extent.getSRS(),sqidTextMap,ALTMODE_ABSOLUTE), mgrsCoord) ) { textSym->size() = 33000.0; osgText::Text* d = ts.create( mgrsCoord.sqid ); osg::Matrixd textLocal2World; ecefSRS->createLocalToWorld( sqidTextECEF, textLocal2World ); d->setPosition( sqidLocal ); textGeode->addDrawable( d ); } } } } } } else if ( letter == 'Y' || letter == 'Z' ) { // SRS for north polar region UPS projection. This projection has (0,0) at the // south pole, with +X extending towards 90 degrees E longitude and +Y towards // 180 degrees longitude. const SpatialReference* ups = SpatialReference::create( "+proj=stere +lat_ts=90 +lat_0=90 +lon_0=0 +k_0=1 +x_0=0 +y_0=0"); osg::Vec3d gtemp; double r = GeoMath::distance(osg::PI_2, 0.0, 1.46607657, 0.0); // 90 -> 84 latitude double r2 = r*r; if ( letter == 'Y' ) { for( double x = 0.0; x < 700000.0; x += 100000.0 ) { double yminmax = sqrt( r2 - x*x ); Feature* f = new Feature( new LineString(2), extent.getSRS() ); f->geoInterp() = GEOINTERP_GREAT_CIRCLE; osg::Vec3d p0, p1; ups->transform( osg::Vec3d(-x, -yminmax, 0), extent.getSRS(), p0 ); ups->transform( osg::Vec3d(-x, yminmax, 0), extent.getSRS(), p1 ); f->getGeometry()->push_back( p0 ); f->getGeometry()->push_back( p1 ); features.push_back( f ); } for( double y = -600000.0; y < 700000.0; y += 100000.0 ) { double xmax = sqrt( r2 - y*y ); Feature* f = new Feature( new LineString(2), extent.getSRS() ); f->geoInterp() = GEOINTERP_GREAT_CIRCLE; osg::Vec3d p0, p1; ups->transform( osg::Vec3d(-xmax, y, 0), extent.getSRS(), p0 ); ups->transform( osg::Vec3d( 0, y, 0), extent.getSRS(), p1 ); f->getGeometry()->push_back( p0 ); f->getGeometry()->push_back( p1 ); features.push_back( f ); } for( double x = -700000.0; x < 0.0; x += 100000.0 ) { for( double y = -700000.0; y < 700000.0; y += 100000.0 ) { osg::Vec3d sqidTextMap; ups->transform( osg::Vec3d(x+50000.0, y+50000.0, 0), extent.getSRS(), sqidTextMap); if ( sqidTextMap.y() > 84.0 ) { sqidTextMap.z() += 1000.0; osg::Vec3d sqidTextECEF; extent.getSRS()->transform(sqidTextMap, ecefSRS, sqidTextECEF); //extent.getSRS()->transformToECEF(sqidTextMap, sqidTextECEF); osg::Vec3d sqidLocal = sqidTextECEF * world2local; MGRSCoord mgrsCoord; if ( mgrs.transform( GeoPoint(extent.getSRS(),sqidTextMap,ALTMODE_ABSOLUTE), mgrsCoord) ) { textSym->size() = 33000.0; osgText::Text* d = ts.create( mgrsCoord.sqid ); osg::Matrixd textLocal2World; ecefSRS->createLocalToWorld( sqidTextECEF, textLocal2World ); d->setPosition( sqidLocal ); textGeode->addDrawable( d ); } } } } } else if ( letter == 'Z' ) { for( double x = 100000.0; x < 700000.0; x += 100000.0 ) { double yminmax = sqrt( r2 - x*x ); Feature* f = new Feature( new LineString(2), extent.getSRS() ); f->geoInterp() = GEOINTERP_GREAT_CIRCLE; osg::Vec3d p0, p1; ups->transform( osg::Vec3d(x, -yminmax, 0), extent.getSRS(), p0 ); ups->transform( osg::Vec3d(x, yminmax, 0), extent.getSRS(), p1 ); f->getGeometry()->push_back( p0 ); f->getGeometry()->push_back( p1 ); features.push_back( f ); } for( double y = -600000.0; y < 700000.0; y += 100000.0 ) { double xmax = sqrt( r2 - y*y ); Feature* f = new Feature( new LineString(2), extent.getSRS() ); f->geoInterp() = GEOINTERP_GREAT_CIRCLE; osg::Vec3d p0, p1; ups->transform( osg::Vec3d( 0, y, 0), extent.getSRS(), p0 ); ups->transform( osg::Vec3d( xmax, y, 0), extent.getSRS(), p1 ); f->getGeometry()->push_back( p0 ); f->getGeometry()->push_back( p1 ); features.push_back( f ); } for( double x = 0.0; x < 700000.0; x += 100000.0 ) { for( double y = -700000.0; y < 700000.0; y += 100000.0 ) { osg::Vec3d sqidTextMap; ups->transform( osg::Vec3d(x+50000.0, y+50000.0, 0), extent.getSRS(), sqidTextMap); if ( sqidTextMap.y() > 84.0 ) { sqidTextMap.z() += 1000.0; osg::Vec3d sqidTextECEF; extent.getSRS()->transform(sqidTextMap, ecefSRS, sqidTextECEF); //extent.getSRS()->transformToECEF(sqidTextMap, sqidTextECEF); osg::Vec3d sqidLocal = sqidTextECEF * world2local; MGRSCoord mgrsCoord; if ( mgrs.transform( GeoPoint(extent.getSRS(),sqidTextMap,ALTMODE_ABSOLUTE), mgrsCoord) ) { textSym->size() = 33000.0; osgText::Text* d = ts.create( mgrsCoord.sqid ); osg::Matrixd textLocal2World; ecefSRS->createLocalToWorld( sqidTextECEF, textLocal2World ); d->setPosition( sqidLocal ); textGeode->addDrawable( d ); } } } } } } osg::Group* group = new osg::Group(); Style lineStyle; lineStyle.add( _options->secondaryStyle()->get<LineSymbol>() ); lineStyle.add( _options->secondaryStyle()->get<AltitudeSymbol>() ); GeometryCompiler compiler; osg::ref_ptr<Session> session = new Session( getMapNode()->getMap() ); FilterContext context( session.get(), _featureProfile.get(), extent ); // make sure we get sufficient tessellation: compiler.options().maxGranularity() = 0.25; osg::Node* geomNode = compiler.compile(features, lineStyle, context); if ( geomNode ) group->addChild( geomNode ); osg::MatrixTransform* mt = new osg::MatrixTransform(local2world); mt->addChild(textGeode); group->addChild( mt ); // prep for depth offset: DepthOffsetUtils::prepareGraph( group ); group->getOrCreateStateSet()->addUniform( _minDepthOffset.get() ); return group; }
// // NOTE: run this sample from the repo/tests directory. // int main(int argc, char** argv) { osg::ArgumentParser arguments(&argc,argv); if ( arguments.read("--help") ) return usage( argv[0] ); bool useRaster = arguments.read("--rasterize"); bool useOverlay = arguments.read("--overlay"); bool useStencil = arguments.read("--stencil"); bool useMem = arguments.read("--mem"); bool useLabels = arguments.read("--labels"); if ( useStencil ) osg::DisplaySettings::instance()->setMinimumNumStencilBits( 8 ); osgViewer::Viewer viewer(arguments); // Start by creating the map: Map* map = new Map(); // Start with a basemap imagery layer; we'll be using the GDAL driver // to load a local GeoTIFF file: GDALOptions basemapOpt; basemapOpt.url() = "../data/world.tif"; map->addImageLayer( new ImageLayer( ImageLayerOptions("basemap", basemapOpt) ) ); // Next we add a feature layer. OGRFeatureOptions featureOptions; if ( !useMem ) { // Configures the feature driver to load the vectors from a shapefile: featureOptions.url() = "../data/world.shp"; } else { // the --mem options tells us to just make an in-memory geometry: Ring* line = new Ring(); line->push_back( osg::Vec3d(-60, 20, 0) ); line->push_back( osg::Vec3d(-120, 20, 0) ); line->push_back( osg::Vec3d(-120, 60, 0) ); line->push_back( osg::Vec3d(-60, 60, 0) ); featureOptions.geometry() = line; } // Define a style for the feature data. Since we are going to render the // vectors as lines, configure the line symbolizer: Style style; LineSymbol* ls = style.getOrCreateSymbol<LineSymbol>(); ls->stroke()->color() = Color::Yellow; ls->stroke()->width() = 2.0f; // That's it, the map is ready; now create a MapNode to render the Map: MapNodeOptions mapNodeOptions; mapNodeOptions.enableLighting() = false; MapNode* mapNode = new MapNode( map, mapNodeOptions ); osg::Group* root = new osg::Group(); root->addChild( mapNode ); viewer.setSceneData( root ); viewer.setCameraManipulator( new EarthManipulator() ); // Process cmdline args MapNodeHelper().parse(mapNode, arguments, &viewer, root, new LabelControl("Features Demo")); if (useStencil) { FeatureStencilModelOptions stencilOptions; stencilOptions.featureOptions() = featureOptions; stencilOptions.styles() = new StyleSheet(); stencilOptions.styles()->addStyle( style ); stencilOptions.enableLighting() = false; stencilOptions.depthTestEnabled() = false; ls->stroke()->width() = 0.1f; map->addModelLayer( new ModelLayer("my features", stencilOptions) ); } else if (useRaster) { AGGLiteOptions rasterOptions; rasterOptions.featureOptions() = featureOptions; rasterOptions.styles() = new StyleSheet(); rasterOptions.styles()->addStyle( style ); map->addImageLayer( new ImageLayer("my features", rasterOptions) ); } else //if (useGeom || useOverlay) { FeatureGeomModelOptions geomOptions; geomOptions.featureOptions() = featureOptions; geomOptions.styles() = new StyleSheet(); geomOptions.styles()->addStyle( style ); geomOptions.enableLighting() = false; ModelLayerOptions layerOptions( "my features", geomOptions ); map->addModelLayer( new ModelLayer(layerOptions) ); } if ( useLabels ) { // set up symbology for drawing labels. We're pulling the label // text from the name attribute, and its draw priority from the // population attribute. Style labelStyle; TextSymbol* text = labelStyle.getOrCreateSymbol<TextSymbol>(); text->content() = StringExpression( "[cntry_name]" ); text->priority() = NumericExpression( "[pop_cntry]" ); text->removeDuplicateLabels() = true; text->size() = 16.0f; text->alignment() = TextSymbol::ALIGN_CENTER_CENTER; text->fill()->color() = Color::White; text->halo()->color() = Color::DarkGray; // and configure a model layer: FeatureGeomModelOptions geomOptions; geomOptions.featureOptions() = featureOptions; geomOptions.styles() = new StyleSheet(); geomOptions.styles()->addStyle( labelStyle ); map->addModelLayer( new ModelLayer("labels", geomOptions) ); } if ( !useStencil ) viewer.getCamera()->addCullCallback( new osgEarth::Util::AutoClipPlaneCullCallback(mapNode) ); // add some stock OSG handlers: viewer.addEventHandler(new osgViewer::StatsHandler()); viewer.addEventHandler(new osgViewer::WindowSizeHandler()); viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())); return viewer.run(); }
void KML_Placemark::build( xml_node<>* node, KMLContext& cx ) { Style masterStyle; std::string styleUrl = getValue(node, "styleurl"); if (!styleUrl.empty()) { // process a "stylesheet" style const Style* ref_style = cx._sheet->getStyle( styleUrl, false ); if (ref_style) { masterStyle = masterStyle.combineWith(*ref_style); } } xml_node<>* style = node->first_node("style", 0, false); if ( style ) { // process an "inline" style KML_Style kmlStyle; kmlStyle.scan(style, cx); masterStyle = masterStyle.combineWith(cx._activeStyle); } // parse the geometry. the placemark must have geometry to be valid. The // geometry parse may optionally specify an altitude mode as well. KML_Geometry geometry; geometry.build(node, cx, masterStyle); Geometry* allGeom = geometry._geom.get(); if ( allGeom ) { GeometryIterator giter( allGeom, false ); while( giter.hasMore() ) { Geometry* geom = giter.next(); Style style = masterStyle; AltitudeSymbol* alt = style.get<AltitudeSymbol>(); if ( geom && geom->getTotalPointCount() > 0 ) { // resolve the proper altitude mode for the anchor point AltitudeMode altMode = ALTMODE_RELATIVE; if (alt && !alt->clamping().isSetTo( alt->CLAMP_TO_TERRAIN ) && !alt->clamping().isSetTo( alt->CLAMP_RELATIVE_TO_TERRAIN ) ) { altMode = ALTMODE_ABSOLUTE; } GeoPoint position(cx._srs.get(), geom->getBounds().center(), altMode); bool isPoly = geom->getComponentType() == Geometry::TYPE_POLYGON; bool isPoint = geom->getComponentType() == Geometry::TYPE_POINTSET; // check for symbols. ModelSymbol* model = style.get<ModelSymbol>(); IconSymbol* icon = style.get<IconSymbol>(); TextSymbol* text = style.get<TextSymbol>(); // the annotation name: std::string name = getValue(node, "name"); AnnotationNode* featureNode = 0L; AnnotationNode* iconNode = 0L; AnnotationNode* modelNode = 0L; // one coordinate? It's a place marker or a label. if ( (model || icon || text) && geom->getTotalPointCount() == 1 ) { // load up the default icon if there we don't have one. if ( !model && !icon ) { icon = cx._options->defaultIconSymbol().get(); if ( icon ) style.add( icon ); } // if there's a model, render that - models do NOT get labels. if ( model ) { ModelNode* node = new ModelNode( cx._mapNode, style, cx._dbOptions ); node->setPosition( position ); // model scale: if ( cx._options->modelScale() != 1.0f ) { float s = *cx._options->modelScale(); node->setScale( osg::Vec3f(s,s,s) ); } // model local tangent plane rotation: if ( !cx._options->modelRotation()->zeroRotation() ) { node->setLocalRotation( *cx._options->modelRotation() ); } modelNode = node; } // is there a label? else if ( !name.empty() ) { if ( !text && cx._options->defaultTextSymbol().valid() ) { text = cx._options->defaultTextSymbol().get(); style.addSymbol( text ); } else { text = style.getOrCreate<TextSymbol>(); text->encoding() = TextSymbol::ENCODING_UTF8; } text->content()->setLiteral( name ); } // is there an icon? if ( icon ) { iconNode = new PlaceNode( cx._mapNode, position, style, cx._dbOptions ); } else if ( !model && text && !name.empty() ) { // note: models do not get labels. iconNode = new LabelNode( cx._mapNode, position, style ); } } // multiple coords? feature: if ( geom->getTotalPointCount() > 1 ) { ExtrusionSymbol* extruded = style.get<ExtrusionSymbol>(); // Remove symbols that we have already processed so the geometry // compiler doesn't get confused. if ( model ) style.removeSymbol( model ); if ( icon ) style.removeSymbol( icon ); if ( text ) style.removeSymbol( text ); Feature* feature = new Feature(geom, cx._srs.get(), style); featureNode = new FeatureNode( cx._mapNode, feature ); } // assemble the results: if ( (iconNode || modelNode) && featureNode ) { osg::Group* group = new osg::Group(); group->addChild( featureNode ); if ( iconNode ) group->addChild( iconNode ); if ( modelNode ) group->addChild( modelNode ); cx._groupStack.top()->addChild( group ); if ( iconNode && cx._options->declutter() == true ) { Decluttering::setEnabled( iconNode->getOrCreateStateSet(), true ); } if ( iconNode ) KML_Feature::build( node, cx, iconNode ); if ( modelNode ) KML_Feature::build( node, cx, modelNode ); if ( featureNode ) KML_Feature::build( node, cx, featureNode ); } else { if ( iconNode ) { if ( cx._options->iconAndLabelGroup().valid() ) { cx._options->iconAndLabelGroup()->addChild( iconNode ); } else { cx._groupStack.top()->addChild( iconNode ); if ( cx._options->declutter() == true ) { Decluttering::setEnabled( iconNode->getOrCreateStateSet(), true ); } } KML_Feature::build( node, cx, iconNode ); } if ( modelNode ) { cx._groupStack.top()->addChild( modelNode ); KML_Feature::build( node, cx, modelNode ); } if ( featureNode ) { cx._groupStack.top()->addChild( featureNode ); KML_Feature::build( node, cx, featureNode ); } } } } } }
/** * Creates a complete set of positioned label nodes from a feature list. */ osg::Node* createNode( const FeatureList& input, const Style& style, FilterContext& context ) { if ( style.get<TextSymbol>() == 0L && style.get<IconSymbol>() == 0L ) return 0L; // copy the style so we can (potentially) modify the text symbol. Style styleCopy = style; TextSymbol* text = styleCopy.get<TextSymbol>(); IconSymbol* icon = styleCopy.get<IconSymbol>(); osg::Group* group = new osg::Group(); StringExpression textContentExpr ( text ? *text->content() : StringExpression() ); NumericExpression textPriorityExpr( text ? *text->priority() : NumericExpression() ); NumericExpression textSizeExpr ( text ? *text->size() : NumericExpression() ); StringExpression iconUrlExpr ( icon ? *icon->url() : StringExpression() ); NumericExpression iconScaleExpr ( icon ? *icon->scale() : NumericExpression() ); NumericExpression iconHeadingExpr ( icon ? *icon->heading() : NumericExpression() ); for( FeatureList::const_iterator i = input.begin(); i != input.end(); ++i ) { Feature* feature = i->get(); if ( !feature ) continue; // run a symbol script if present. if ( text && text->script().isSet() ) { StringExpression temp( text->script().get() ); feature->eval( temp, &context ); } // run a symbol script if present. if ( icon && icon->script().isSet() ) { StringExpression temp( icon->script().get() ); feature->eval( temp, &context ); } const Geometry* geom = feature->getGeometry(); if ( !geom ) continue; Style tempStyle = styleCopy; // evaluate expressions into literals. // TODO: Later we could replace this with a generate "expression evaluator" type // that we could pass to PlaceNode in the DB options. -gw if ( text ) { if ( text->content().isSet() ) tempStyle.get<TextSymbol>()->content()->setLiteral( feature->eval( textContentExpr, &context ) ); if ( text->size().isSet() ) tempStyle.get<TextSymbol>()->size()->setLiteral( feature->eval(textSizeExpr, &context) ); } if ( icon ) { if ( icon->url().isSet() ) tempStyle.get<IconSymbol>()->url()->setLiteral( feature->eval(iconUrlExpr, &context) ); if ( icon->scale().isSet() ) tempStyle.get<IconSymbol>()->scale()->setLiteral( feature->eval(iconScaleExpr, &context) ); if ( icon->heading().isSet() ) tempStyle.get<IconSymbol>()->heading()->setLiteral( feature->eval(iconHeadingExpr, &context) ); } osg::Node* node = makePlaceNode( context, feature, tempStyle, textPriorityExpr); if ( node ) { if ( context.featureIndex() ) { context.featureIndex()->tagNode(node, feature); } group->addChild( node ); } } // Note to self: need to change this to support picking later. -gw //VirtualProgram* vp = VirtualProgram::getOrCreate(group->getOrCreateStateSet()); //vp->setInheritShaders( false ); return group; }
void GeodeticGraticule::rebuild() { this->removeChildren( 0, this->getNumChildren() ); if ( !getMapNode() ) { OE_WARN << LC << "Illegal NULL map node" << std::endl; return; } if ( !getMapNode()->isGeocentric() ) { OE_WARN << LC << "Projected map mode is not yet supported" << std::endl; return; } const Profile* mapProfile = _mapNode->getMap()->getProfile(); _profile = Profile::create( mapProfile->getSRS(), mapProfile->getExtent().xMin(), mapProfile->getExtent().yMin(), mapProfile->getExtent().xMax(), mapProfile->getExtent().yMax(), 8, 4 ); _featureProfile = new FeatureProfile(_profile->getSRS()); //todo: do this right.. osg::StateSet* set = this->getOrCreateStateSet(); set->setRenderBinDetails( 9999, "RenderBin" ); set->setMode( GL_LIGHTING, 0 ); // set up default options if the caller did not supply them if ( !_options.isSet() ) { _options->lineStyle() = Style(); LineSymbol* line = _options->lineStyle()->getOrCreate<LineSymbol>(); line->stroke()->color() = Color::Gray; line->stroke()->width() = 1.0; AltitudeSymbol* alt = _options->lineStyle()->getOrCreate<AltitudeSymbol>(); alt->verticalOffset() = NumericExpression(5000.0); _options->textStyle() = Style(); TextSymbol* text = _options->textStyle()->getOrCreate<TextSymbol>(); text->alignment() = TextSymbol::ALIGN_CENTER_CENTER; if ( _mapNode->isGeocentric() ) { double r = _mapNode->getMapSRS()->getEllipsoid()->getRadiusEquator(); _options->addLevel( FLT_MAX, 0.0f, 1u ); double d = 4.5*r; for(int i=0; i<3; i++) { d *= 0.5; _options->addLevel( d, d*0.25 ); } } else { //todo? } } _root = new DrapeableNode( _mapNode.get(), false ); this->addChild( _root ); // need at least one level if ( _options->levels().size() < 1 ) return; const GeodeticGraticuleOptions::Level& level0 = _options->levels()[0]; // build the top level cell grid. unsigned tilesX, tilesY; _profile->getNumTiles( 0, tilesX, tilesY ); for( unsigned tx = 0; tx < tilesX; ++tx ) { for( unsigned ty = 0; ty < tilesY; ++ty ) { TileKey key( 0, tx, ty, _profile.get() ); osg::Node* tile = buildTile( key, getMapNode()->getMap() ); if ( tile ) _root->addChild( tile ); } } }
void PlaceNode::setText( const std::string& text ) { if ( !_dynamic ) { OE_WARN << LC << "Illegal state: cannot change a LabelNode that is not dynamic" << std::endl; return; } _text = text; const osg::Geode::DrawableList& list = _geode->getDrawableList(); for( osg::Geode::DrawableList::const_iterator i = list.begin(); i != list.end(); ++i ) { osgText::Text* d = dynamic_cast<osgText::Text*>( i->get() ); if ( d ) { TextSymbol* symbol = _style.getOrCreate<TextSymbol>(); osgText::String::Encoding text_encoding = osgText::String::ENCODING_UNDEFINED; if ( symbol && symbol->encoding().isSet() ) { text_encoding = AnnotationUtils::convertTextSymbolEncoding(symbol->encoding().value()); } d->setText( text, text_encoding ); break; } } }