/** * 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); }
/** * 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; }
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; }
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; }
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; }
// // 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(); }
// // 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(); }