Config FeatureNode::getConfig() const { Config conf("feature"); if ( !_features.empty() ) { // Write out a single feature for now. Feature* feature = _features.begin()->get(); conf.set("name", getName()); Config geomConf("geometry"); geomConf.value() = GeometryUtils::geometryToWKT( feature->getGeometry() ); conf.add(geomConf); std::string srs = feature->getSRS() ? feature->getSRS()->getHorizInitString() : ""; if ( !srs.empty() ) conf.set("srs", srs); std::string vsrs = feature->getSRS() ? feature->getSRS()->getVertInitString() : ""; if ( !vsrs.empty() ) conf.set("vdatum", vsrs); if ( feature->geoInterp().isSet() ) conf.set("geointerp", feature->geoInterp() == GEOINTERP_GREAT_CIRCLE? "greatcircle" : "rhumbline"); } if (!_style.empty() ) { conf.set( "style", _style ); } return conf; }
bool AddPointHandler::addPoint( float x, float y, osgViewer::View* view ) { osg::Vec3d world; MapNode* mapNode = _featureNode->getMapNode(); if ( mapNode->getTerrain()->getWorldCoordsUnderMouse( view, x, y, world ) ) { // Get the map point from the world GeoPoint mapPoint; mapPoint.fromWorld( mapNode->getMapSRS(), world ); Feature* feature = _featureNode->getFeature(); if ( feature ) { // Convert the map point to the feature's SRS GeoPoint featurePoint = mapPoint.transform( feature->getSRS() ); feature->getGeometry()->push_back( featurePoint.vec3d() ); _featureNode->init(); return true; } } return false; }
virtual void traverse( FeatureTile* tile) { if (tile->getFeatures().size() > 0) { //Actually load up the features FeatureList features; for (FeatureIDList::const_iterator i = tile->getFeatures().begin(); i != tile->getFeatures().end(); i++) { Feature* f = _features->getFeature( *i ); if (f) { //Reproject the feature to the dest SRS if it's not already if (!f->getSRS()->isEquivalentTo( _srs ) ) { f->transform( _srs ); } features.push_back( f ); } else { OE_NOTICE << "couldn't get feature " << *i << std::endl; } } //Need to do the cropping again since these are brand new features coming from the feature source. CropFilter cropFilter(_cropMethod); FilterContext context(0); context.extent() = tile->getExtent(); cropFilter.push( features, context ); std::string contents = Feature::featuresToGeoJSON( features ); std::stringstream buf; int x = tile->getKey().getTileX(); unsigned int numRows, numCols; tile->getKey().getProfile()->getNumTiles(tile->getKey().getLevelOfDetail(), numCols, numRows); int y = numRows - tile->getKey().getTileY() - 1; buf << _dest << "/" << tile->getKey().getLevelOfDetail() << "/" << x << "/" << y << ".json"; std::string filename = buf.str(); //OE_NOTICE << "Writing " << features.size() << " features to " << filename << std::endl; if ( !osgDB::fileExists( osgDB::getFilePath(filename) ) ) osgEarth::makeDirectoryForFile( filename ); std::fstream output( filename.c_str(), std::ios_base::out ); if ( output.is_open() ) { output << contents; output.flush(); output.close(); } } tile->traverse( this ); }
void FeatureEditor::init() { removeChildren( 0, getNumChildren() ); Feature* feature = _featureNode->getFeature(); //Create a dragger for each point for (unsigned int i = 0; i < _featureNode->getFeature()->getGeometry()->size(); i++) { SphereDragger* dragger = new SphereDragger( _featureNode->getMapNode() ); dragger->setColor( _color ); dragger->setPickColor( _pickColor ); dragger->setSize( _size ); dragger->setPosition(GeoPoint(feature->getSRS(), (*feature->getGeometry())[i].x(), (*feature->getGeometry())[i].y())); dragger->addPositionChangedCallback(new MoveFeatureDraggerCallback( _featureNode.get(), i) ); addChild(dragger); } }
void FeatureNode::build() { if ( !_clampCallback.valid() ) _clampCallback = new ClampCallback(this); _attachPoint = 0L; // if there is existing geometry, kill it this->removeChildren( 0, this->getNumChildren() ); if ( !getMapNode() ) return; if ( _features.empty() ) return; const Style &style = getStyle(); // compilation options. GeometryCompilerOptions options = _options; // figure out what kind of altitude manipulation we need to perform. AnnotationUtils::AltitudePolicy ap; AnnotationUtils::getAltitudePolicy( style, ap ); // If we're doing auto-clamping on the CPU, shut off compiler map clamping // clamping since it would be redundant. if ( ap.sceneClamping ) { options.ignoreAltitudeSymbol() = true; } _clamperData.clear(); osg::Node* node = _compiled.get(); if (_needsRebuild || !_compiled.valid() ) { // Clone the Features before rendering as the GeometryCompiler and it's filters can change the coordinates // of the geometry when performing localization or converting to geocentric. _extent = GeoExtent::INVALID; FeatureList clone; for(FeatureList::iterator itr = _features.begin(); itr != _features.end(); ++itr) { Feature* feature = new Feature( *itr->get(), osg::CopyOp::DEEP_COPY_ALL); GeoExtent featureExtent(feature->getSRS(), feature->getGeometry()->getBounds()); if (_extent.isInvalid()) { _extent = featureExtent; } else { _extent.expandToInclude( featureExtent ); } clone.push_back( feature ); } // prep the compiler: GeometryCompiler compiler( options ); Session* session = new Session( getMapNode()->getMap(), _styleSheet.get() ); FilterContext context( session, new FeatureProfile( _extent ), _extent, _index); _compiled = compiler.compile( clone, style, context ); node = _compiled.get(); _needsRebuild = false; // Compute the world bounds osg::BoundingSphered bounds; for( FeatureList::iterator itr = _features.begin(); itr != _features.end(); ++itr) { osg::BoundingSphered bs; itr->get()->getWorldBound(getMapNode()->getMapSRS(), bs); bounds.expandBy(bs); } // The polytope will ensure we only clamp to intersecting tiles: Feature::getWorldBoundingPolytope(bounds, getMapNode()->getMapSRS(), _featurePolytope); } if ( node ) { if ( AnnotationUtils::styleRequiresAlphaBlending( style ) && getStyle().get<ExtrusionSymbol>() ) { node = AnnotationUtils::installTwoPassAlpha( node ); } _attachPoint = new osg::Group(); _attachPoint->addChild( node ); // Draped (projected) geometry if ( ap.draping ) { DrapeableNode* d = new DrapeableNode(); d->addChild( _attachPoint ); this->addChild( d ); } // GPU-clamped geometry else if ( ap.gpuClamping ) { ClampableNode* clampable = new ClampableNode(); clampable->addChild( _attachPoint ); this->addChild( clampable ); } else { this->addChild( _attachPoint ); // set default lighting based on whether we are extruding: setDefaultLighting( style.has<ExtrusionSymbol>() ); } applyRenderSymbology(style); if ( getMapNode()->getTerrain() ) { if ( ap.sceneClamping ) { // Need dynamic data variance since scene clamping will change the verts SetDataVarianceVisitor sdv(osg::Object::DYNAMIC); this->accept(sdv); getMapNode()->getTerrain()->addTerrainCallback(_clampCallback.get()); clamp(getMapNode()->getTerrain()->getGraph(), getMapNode()->getTerrain()); } else { getMapNode()->getTerrain()->removeTerrainCallback( _clampCallback.get() ); } } } }
void FeatureNode::build() { // if there's a decoration, clear it out first. this->clearDecoration(); _attachPoint = 0L; // if there is existing geometry, kill it this->removeChildren( 0, this->getNumChildren() ); if ( !getMapNode() ) return; if ( _features.empty() ) return; const Style &style = getStyle(); // compilation options. GeometryCompilerOptions options = _options; // figure out what kind of altitude manipulation we need to perform. AnnotationUtils::AltitudePolicy ap; AnnotationUtils::getAltitudePolicy( style, ap ); // If we're doing auto-clamping on the CPU, shut off compiler map clamping // clamping since it would be redundant. // TODO: I think this is OBE now that we have "scene" clamping technique.. if ( ap.sceneClamping ) { options.ignoreAltitudeSymbol() = true; } osg::Node* node = _compiled.get(); if (_needsRebuild || !_compiled.valid() ) { // Clone the Features before rendering as the GeometryCompiler and it's filters can change the coordinates // of the geometry when performing localization or converting to geocentric. _extent = GeoExtent::INVALID; FeatureList clone; for(FeatureList::iterator itr = _features.begin(); itr != _features.end(); ++itr) { Feature* feature = new Feature( *itr->get(), osg::CopyOp::DEEP_COPY_ALL); GeoExtent featureExtent(feature->getSRS(), feature->getGeometry()->getBounds()); if (_extent.isInvalid()) { _extent = featureExtent; } else { _extent.expandToInclude( featureExtent ); } clone.push_back( feature ); } // prep the compiler: GeometryCompiler compiler( options ); Session* session = new Session( getMapNode()->getMap(), _styleSheet.get() ); FilterContext context( session, new FeatureProfile( _extent ), _extent ); _compiled = compiler.compile( clone, style, context ); node = _compiled.get(); _needsRebuild = false; // Compute the world bounds osg::BoundingSphered bounds; for( FeatureList::iterator itr = _features.begin(); itr != _features.end(); ++itr) { osg::BoundingSphered bs; itr->get()->getWorldBound(getMapNode()->getMapSRS(), bs); bounds.expandBy(bs); } // The polytope will ensure we only clamp to intersecting tiles: Feature::getWorldBoundingPolytope(bounds, getMapNode()->getMapSRS(), _featurePolytope); } if ( node ) { if ( AnnotationUtils::styleRequiresAlphaBlending( style ) && getStyle().get<ExtrusionSymbol>() ) { node = AnnotationUtils::installTwoPassAlpha( node ); } //OE_NOTICE << GeometryUtils::geometryToGeoJSON( _feature->getGeometry() ) << std::endl; _attachPoint = new osg::Group(); _attachPoint->addChild( node ); // Draped (projected) geometry if ( ap.draping ) { DrapeableNode* d = new DrapeableNode(); // getMapNode() ); d->addChild( _attachPoint ); this->addChild( d ); } // GPU-clamped geometry else if ( ap.gpuClamping ) { ClampableNode* clampable = new ClampableNode( getMapNode() ); clampable->addChild( _attachPoint ); this->addChild( clampable ); const RenderSymbol* render = style.get<RenderSymbol>(); if ( render && render->depthOffset().isSet() ) { clampable->setDepthOffsetOptions( *render->depthOffset() ); } } else { this->addChild( _attachPoint ); // CPU-clamped geometry? if ( ap.sceneClamping ) { // save for later when we need to reclamp the mesh on the CPU _altitude = style.get<AltitudeSymbol>(); // activate the terrain callback: setCPUAutoClamping( true ); // set default lighting based on whether we are extruding: setLightingIfNotSet( style.has<ExtrusionSymbol>() ); // do an initial clamp to get started. clampMesh( getMapNode()->getTerrain()->getGraph() ); } applyRenderSymbology( style ); } } updateClusterCulling(); }
FilterContext push(FeatureList& input, FilterContext& context) { if (_featureSource.valid()) { // Get any features that intersect this query. FeatureList boundaries; getFeatures(context.extent().get(), boundaries ); // The list of output features FeatureList output; if (boundaries.empty()) { // No intersecting features. If contains is false, then just the output to the input. if (contains() == false) { output = input; } } else { // Transform the boundaries into the coordinate system of the features for (FeatureList::iterator itr = boundaries.begin(); itr != boundaries.end(); ++itr) { itr->get()->transform( context.profile()->getSRS() ); } for(FeatureList::const_iterator f = input.begin(); f != input.end(); ++f) { Feature* feature = f->get(); if ( feature && feature->getGeometry() ) { osg::Vec2d c = feature->getGeometry()->getBounds().center2d(); if ( contains() == true ) { // coarsest: if (_featureSource->getFeatureProfile()->getExtent().contains(GeoPoint(feature->getSRS(), c.x(), c.y()))) { for (FeatureList::iterator itr = boundaries.begin(); itr != boundaries.end(); ++itr) { Ring* ring = dynamic_cast< Ring*>(itr->get()->getGeometry()); if (ring && ring->contains2D(c.x(), c.y())) { output.push_back( feature ); } } } } else { bool contained = false; // coarsest: if (_featureSource->getFeatureProfile()->getExtent().contains(GeoPoint(feature->getSRS(), c.x(), c.y()))) { for (FeatureList::iterator itr = boundaries.begin(); itr != boundaries.end(); ++itr) { Ring* ring = dynamic_cast< Ring*>(itr->get()->getGeometry()); if (ring && ring->contains2D(c.x(), c.y())) { contained = true; break; } } } if ( !contained ) { output.push_back( feature ); } } } } } OE_INFO << LC << "Allowed " << output.size() << " out of " << input.size() << " features\n"; input = output; } return context; }