void LocalGeometryNode::initGeometry(const osgDB::Options* dbOptions) { // reset osgEarth::clearChildren( this ); osgEarth::clearChildren( _xform.get() ); this->addChild( _xform.get() ); if ( _geom.valid() ) { Session* session = 0L; if ( getMapNode() ) session = new Session(getMapNode()->getMap(), 0L, 0L, dbOptions); FilterContext cx( session ); GeometryCompiler gc; osg::Node* node = gc.compile( _geom.get(), _style, cx ); if ( node ) { _xform->addChild( node ); // activate clamping if necessary replaceChild( _xform.get(), applyAltitudePolicy(_xform.get(), _style) ); applyGeneralSymbology( _style ); } } }
void EllipseNode::rebuild() { osgEarth::clearChildren( getPositionAttitudeTransform() ); // construct a local-origin ellipse. GeometryFactory factory; Geometry* geom = NULL; if (std::abs(_arcEnd.as(Units::DEGREES) - _arcStart.as(Units::DEGREES)) >= 360.0) { geom = factory.createEllipse(osg::Vec3d(0,0,0), _radiusMajor, _radiusMinor, _rotationAngle, _numSegments); } else { geom = factory.createEllipticalArc(osg::Vec3d(0,0,0), _radiusMajor, _radiusMinor, _rotationAngle, _arcStart, _arcEnd, _numSegments, 0L, _pie); } if ( geom ) { GeometryCompiler compiler; osg::ref_ptr<Feature> feature = new Feature(geom, 0L); //todo: consider the SRS osg::ref_ptr<osg::Node> node = compiler.compile( feature.get(), _style, FilterContext(0L) ); if ( node ) { node = AnnotationUtils::installOverlayParent(node.get(), _style); getPositionAttitudeTransform()->addChild( node.get() ); } applyRenderSymbology( _style ); setLightingIfNotSet( false ); } }
LocalGeometryNode::LocalGeometryNode(MapNode* mapNode, Geometry* geom, const Style& style, bool draped, osg::Group* parent ) : DrapeableNode( mapNode, draped ) { osg::ref_ptr<Feature> feature = new Feature( geom ); GeometryCompiler compiler; FilterContext cx( 0L ); osg::Node* node = compiler.compile( feature.get(), style, cx ); if ( node ) { if ( parent ) { parent->addChild( node ); setNode( parent ); } else { setNode( node ); } } }
void CircleNode::rebuild() { std::string currentDecoration = getDecoration(); clearDecoration(); //Remove all children from this node //removeChildren( 0, getNumChildren() ); if ( getRoot()->getNumParents() == 0 ) { this->addChild( getRoot() ); } //Remove all children from the attach point getChildAttachPoint()->removeChildren( 0, getChildAttachPoint()->getNumChildren() ); // construct a local-origin circle. GeometryFactory factory; Geometry* geom = factory.createCircle(osg::Vec3d(0,0,0), _radius, _numSegments); if ( geom ) { GeometryCompiler compiler; osg::ref_ptr<Feature> feature = new Feature(geom, 0L); //todo: consider the SRS osg::Node* node = compiler.compile( feature.get(), _style, FilterContext(0L) ); if ( node ) { getChildAttachPoint()->addChild( node ); getDrapeable()->setDraped( _draped ); } applyStyle( _style ); } setDecoration( currentDecoration ); }
void LocalGeometryNode::initGeometry(const osgDB::Options* dbOptions) { osgEarth::clearChildren( getPositionAttitudeTransform() ); if ( _geom.valid() ) { osg::ref_ptr<Session> session; if ( getMapNode() ) session = new Session(getMapNode()->getMap(), 0L, 0L, dbOptions); GeometryCompiler gc; osg::ref_ptr<osg::Node> node = gc.compile( _geom.get(), getStyle(), FilterContext(session) ); if ( node.valid() ) { node = AnnotationUtils::installOverlayParent( node.get(), getStyle() ); getPositionAttitudeTransform()->addChild( node.get() ); applyRenderSymbology( getStyle() ); applyAltitudeSymbology( getStyle() ); } } }
void RectangleNode::rebuild() { std::string currentDecoration = getDecoration(); clearDecoration(); // Reset: osgEarth::clearChildren( this ); osgEarth::clearChildren( _xform.get() ); this->addChild( _xform.get() ); // construct a local-origin circle. GeometryFactory factory; Geometry* geom = factory.createRectangle(osg::Vec3d(0,0,0), _width, _height); if ( geom ) { GeometryCompiler compiler; osg::ref_ptr<Feature> feature = new Feature(geom, 0L); //todo: consider the SRS osg::Node* node = compiler.compile( feature.get(), _style, FilterContext(0L) ); if ( node ) { _xform->addChild( node ); replaceChild( _xform.get(), applyAltitudePolicy(_xform.get(), _style) ); } applyRenderSymbology( _style ); setLightingIfNotSet( false ); } setDecoration( currentDecoration ); }
void EllipseNode::rebuild() { std::string currentDecoration = getDecoration(); clearDecoration(); //Remove all children from this node removeChildren( 0, getNumChildren() ); //Remove all children from the attach point getAttachPoint()->removeChildren( 0, getAttachPoint()->getNumChildren() ); // construct a local-origin ellipse. GeometryFactory factory; Geometry* geom = factory.createEllipse(osg::Vec3d(0,0,0), _radiusMajor, _radiusMinor, _rotationAngle, _numSegments); if ( geom ) { GeometryCompiler compiler; osg::ref_ptr<Feature> feature = new Feature(geom, 0L); //todo: consider the SRS osg::Node* node = compiler.compile( feature.get(), _style, FilterContext(0L) ); if ( node ) { getAttachPoint()->addChild( node ); if ( _draped ) { DrapeableNode* drapeable = new DrapeableNode( _mapNode.get() ); drapeable->addChild( getAttachPoint() ); this->addChild( drapeable ); } else { this->addChild( getAttachPoint() ); } } applyStyle( _style, _draped ); } setDecoration( currentDecoration ); }
void EllipseNode::rebuild() { std::string currentDecoration = getDecoration(); clearDecoration(); //Remove all children from this node osgEarth::clearChildren( this ); osgEarth::clearChildren( _xform.get() ); this->addChild( _xform.get() ); // construct a local-origin ellipse. GeometryFactory factory; Geometry* geom = NULL; if (std::abs(_arcEnd.as(Units::DEGREES) - _arcStart.as(Units::DEGREES)) >= 360.0) { geom = factory.createEllipse(osg::Vec3d(0,0,0), _radiusMajor, _radiusMinor, _rotationAngle, _numSegments); } else { geom = factory.createEllipticalArc(osg::Vec3d(0,0,0), _radiusMajor, _radiusMinor, _rotationAngle, _arcStart, _arcEnd, _numSegments, 0L, _pie); } if ( geom ) { GeometryCompiler compiler; osg::ref_ptr<Feature> feature = new Feature(geom, 0L); //todo: consider the SRS osg::Node* node = compiler.compile( feature.get(), _style, FilterContext(0L) ); if ( node ) { _xform->addChild( node ); this->replaceChild( _xform.get(), applyAltitudePolicy(_xform.get(), _style) ); } applyRenderSymbology( _style ); setLightingIfNotSet( false ); } setDecoration( currentDecoration ); }
void RectangleNode::rebuild() { osgEarth::clearChildren( getPositionAttitudeTransform() ); // construct a local-origin circle. GeometryFactory factory; Geometry* geom = factory.createRectangle(osg::Vec3d(0,0,0), _width, _height); if ( geom ) { GeometryCompiler compiler; osg::ref_ptr<osg::Node> node = compiler.compile( geom, _style, FilterContext() ); if ( node ) { node = AnnotationUtils::installOverlayParent( node.get(), _style ); getPositionAttitudeTransform()->addChild( node.get() ); } applyRenderSymbology( _style ); setLightingIfNotSet( false ); } }
DrapedGeometryNode::DrapedGeometryNode(MapNode* mapNode, Geometry* geom, const Style& style, osg::Group* parent ) : DrapeableNode( mapNode, true ) { osg::ref_ptr<Feature> feature = new Feature( geom ); GeometryCompiler compiler; FilterContext cx( new Session(mapNode->getMap()) ); osg::Node* node = compiler.compile( feature.get(), style, cx ); if ( node ) { if ( parent ) { parent->addChild( node ); setNode( parent ); } else { setNode( node ); } } }
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; }
osg::Group* UTMData::buildGZDTile(const std::string& name, const GeoExtent& extent, const Style& style, const FeatureProfile* featureProfile, const Map* map) { osg::Group* group = new osg::Group(); Style lineStyle; lineStyle.add( const_cast<LineSymbol*>(style.get<LineSymbol>()) ); lineStyle.add( const_cast<AltitudeSymbol*>(style.get<AltitudeSymbol>()) ); bool hasText = style.get<TextSymbol>() != 0L; GeometryCompiler compiler; osg::ref_ptr<Session> session = new Session(map); FilterContext context( session.get(), featureProfile, 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() ); const SpatialReference* ecefSRS = extent.getSRS()->getGeocentricSRS(); osg::Vec3d centerECEF; extent.getSRS()->transform( tileCenter, ecefSRS, centerECEF ); if ( hasText ) { osg::Vec3d west, east; extent.getSRS()->transform( osg::Vec3d(extent.xMin(),tileCenter.y(),0), ecefSRS, west ); extent.getSRS()->transform( osg::Vec3d(extent.xMax(),tileCenter.y(),0), ecefSRS, east ); const TextSymbol* textSym_in = style.get<TextSymbol>(); osg::ref_ptr<TextSymbol> textSym = textSym_in ? new TextSymbol(*textSym_in) : new TextSymbol(); textSym->size() = (west-east).length() / 3.0; TextSymbolizer ts(textSym.get()); osg::Geode* textGeode = new osg::Geode(); osg::Drawable* d = ts.create(name); d->getOrCreateStateSet()->setRenderBinToInherit(); textGeode->addDrawable(d); Registry::shaderGenerator().run(textGeode, Registry::stateSetCache()); osg::Matrixd centerL2W; ecefSRS->createLocalToWorld( centerECEF, centerL2W ); osg::MatrixTransform* mt = new osg::MatrixTransform(centerL2W); mt->addChild(textGeode); group->addChild(mt); } //group = buildGZDChildren( group, name ); group = ClusterCullingFactory::createAndInstall( group, centerECEF )->asGroup(); return group; }
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; }
osg::Node* GeodeticGraticule::buildTile( const TileKey& key, Map* map ) const { if ( _options->levels().size() <= key.getLevelOfDetail() ) { OE_WARN << LC << "Tried to create cell at non-existant level " << key.getLevelOfDetail() << std::endl; return 0L; } const GeodeticGraticuleOptions::Level& level = _options->levels()[key.getLevelOfDetail()]; //_levels[key.getLevelOfDetail()]; // the "-2" here is because normal tile paging gives you one subdivision already, // so we only need to account for > 1 subdivision factor. unsigned cellsPerTile = level._subdivisionFactor <= 2u ? 1u : 1u << (level._subdivisionFactor-2u); unsigned cellsPerTileX = std::max(1u, cellsPerTile); unsigned cellsPerTileY = std::max(1u, cellsPerTile); GeoExtent tileExtent = key.getExtent(); FeatureList latLines; FeatureList lonLines; static LatLongFormatter s_llf(LatLongFormatter::FORMAT_DECIMAL_DEGREES); double cellWidth = tileExtent.width() / cellsPerTileX; double cellHeight = tileExtent.height() / cellsPerTileY; const Style& lineStyle = level._lineStyle.isSet() ? *level._lineStyle : *_options->lineStyle(); const Style& textStyle = level._textStyle.isSet() ? *level._textStyle : *_options->textStyle(); bool hasText = textStyle.get<TextSymbol>() != 0L; osg::ref_ptr<osg::Group> labels; if ( hasText ) { labels = new osg::Group(); //TODO: This is a bug, if you don't turn on decluttering the text labels are giant. Need to determine what is wrong with LabelNodes without decluttering. Decluttering::setEnabled( labels->getOrCreateStateSet(), true ); } // spatial ref for features: const SpatialReference* geoSRS = tileExtent.getSRS()->getGeographicSRS(); // longitude lines for( unsigned cx = 0; cx < cellsPerTileX; ++cx ) { double clon = tileExtent.xMin() + cellWidth * (double)cx; LineString* lon = new LineString(2); lon->push_back( osg::Vec3d(clon, tileExtent.yMin(), 0) ); lon->push_back( osg::Vec3d(clon, tileExtent.yMax(), 0) ); lonLines.push_back( new Feature(lon, geoSRS) ); if ( hasText ) { for( unsigned cy = 0; cy < cellsPerTileY; ++cy ) { double clat = tileExtent.yMin() + (0.5*cellHeight) + cellHeight*(double)cy; LabelNode* label = new LabelNode( _mapNode.get(), GeoPoint(geoSRS, clon, clat), s_llf.format(clon), textStyle ); labels->addChild( label ); } } } // latitude lines for( unsigned cy = 0; cy < cellsPerTileY; ++cy ) { double clat = tileExtent.yMin() + cellHeight * (double)cy; if ( clat == key.getProfile()->getExtent().yMin() ) continue; LineString* lat = new LineString(2); lat->push_back( osg::Vec3d(tileExtent.xMin(), clat, 0) ); lat->push_back( osg::Vec3d(tileExtent.xMax(), clat, 0) ); latLines.push_back( new Feature(lat, geoSRS) ); if ( hasText ) { for( unsigned cx = 0; cx < cellsPerTileX; ++cx ) { double clon = tileExtent.xMin() + (0.5*cellWidth) + cellWidth*(double)cy; LabelNode* label = new LabelNode( _mapNode.get(), GeoPoint(geoSRS, clon, clat), s_llf.format(clat), textStyle ); labels->addChild( label ); } } } osg::Group* group = new osg::Group(); GeometryCompiler compiler; osg::ref_ptr<Session> session = new Session( map ); FilterContext context( session.get(), _featureProfile.get(), tileExtent ); // make sure we get sufficient tessellation: compiler.options().maxGranularity() = std::min(cellWidth, cellHeight) / 16.0; compiler.options().geoInterp() = GEOINTERP_GREAT_CIRCLE; osg::Node* lonNode = compiler.compile(lonLines, lineStyle, context); if ( lonNode ) group->addChild( lonNode ); compiler.options().geoInterp() = GEOINTERP_RHUMB_LINE; osg::Node* latNode = compiler.compile(latLines, lineStyle, context); if ( latNode ) group->addChild( latNode ); // add the labels. if ( labels.valid() ) group->addChild( labels.get() ); // get the geocentric tile center: osg::Vec3d tileCenter; tileExtent.getCentroid( tileCenter.x(), tileCenter.y() ); const SpatialReference* ecefSRS = tileExtent.getSRS()->getECEF(); osg::Vec3d centerECEF; tileExtent.getSRS()->transform( tileCenter, ecefSRS, centerECEF ); //tileExtent.getSRS()->transformToECEF( tileCenter, centerECEF ); osg::NodeCallback* ccc = 0L; // set up cluster culling. if ( tileExtent.getSRS()->isGeographic() && tileExtent.width() < 90.0 && tileExtent.height() < 90.0 ) { ccc = ClusterCullingFactory::create( group, centerECEF ); } // add a paging node for higher LODs: if ( key.getLevelOfDetail() + 1 < _options->levels().size() ) { const GeodeticGraticuleOptions::Level& nextLevel = _options->levels()[key.getLevelOfDetail()+1]; osg::BoundingSphere bs = group->getBound(); std::string uri = Stringify() << key.str() << "_" << getID() << "." << GRID_MARKER << "." << GRATICULE_EXTENSION; osg::PagedLOD* plod = new osg::PagedLOD(); plod->setCenter( bs.center() ); plod->addChild( group, std::max(level._minRange,nextLevel._maxRange), FLT_MAX ); plod->setFileName( 1, uri ); plod->setRange( 1, 0, nextLevel._maxRange ); group = plod; } // or, if this is the deepest level and there's a minRange set, we need an LOD: else if ( level._minRange > 0.0f ) { osg::LOD* lod = new osg::LOD(); lod->addChild( group, level._minRange, FLT_MAX ); group = lod; } if ( ccc ) { osg::Group* cccGroup = new osg::Group(); cccGroup->addCullCallback( ccc ); cccGroup->addChild( group ); group = cccGroup; } return group; }