Exemplo n.º 1
0
    // override
    // Creates an image.
    osg::Image* createImage(const TileKey&    key,
                            ProgressCallback* progress )
    {
        if ( !_imageLayer.valid() || !_featureSource.valid() )
            return 0L;

        // fetch the image for this key:
        GeoImage image = _imageLayer->createImage(key, progress);
        if ( !image.valid() )
            return 0L;

        // fetch a set of features for this key. The features are in their
        // own SRS, so we need to transform:
        const SpatialReference* featureSRS = _featureSource->getFeatureProfile()->getSRS();
        GeoExtent extentInFeatureSRS = key.getExtent().transform( featureSRS );

        // assemble a spatial query. It helps if your features have a spatial index.
        Query query;
        query.bounds() = extentInFeatureSRS.bounds();
        //query.expression() = ... // SQL expression compatible with data source
        osg::ref_ptr<FeatureCursor> cursor = _featureSource->createFeatureCursor(query);

        // create a new image to return.
        osg::Image* output = new osg::Image();
        //output->allocateImage(128, 128, 1, GL_RGB, GL_UNSIGNED_BYTE);

        // do your magic here.

        return output;
    }
 /**
  * Gets all the features that intersect the extent
  */
 void getFeatures(const GeoExtent& extent, FeatureList& features)
 {
     GeoExtent localExtent = extent.transform( _featureSource->getFeatureProfile()->getSRS() );
     Query query;
     query.bounds() = localExtent.bounds();
     if (localExtent.intersects( _featureSource->getFeatureProfile()->getExtent()))
     {
         osg::ref_ptr< FeatureCursor > cursor = _featureSource->createFeatureCursor( query );
         if (cursor)
         {
             cursor->fill( features );
         }
     }     
 }
Exemplo n.º 3
0
void
TileIndex::getFiles(const osgEarth::GeoExtent& extent, std::vector< std::string >& files)
{            
    files.clear();
    osgEarth::Symbology::Query query;    

    GeoExtent transformed = extent.transform( _features->getFeatureProfile()->getSRS() );
    query.bounds() = transformed.bounds();
    osg::ref_ptr< osgEarth::Features::FeatureCursor> cursor = _features->createFeatureCursor( query, 0L );

    while (cursor->hasMore())
    {
        osg::ref_ptr< osgEarth::Features::Feature> feature = cursor->nextFeature();
        if (feature.valid())
        {
            std::string location = getFullPath(_filename, feature->getString("location"));
            files.push_back( location );
        }
    }    
}
Exemplo n.º 4
0
bool TileIndex::add( const std::string& filename, const GeoExtent& extent )
{       
    osg::ref_ptr< Polygon > polygon = new Polygon();
    polygon->push_back( osg::Vec3d(extent.bounds().xMin(), extent.bounds().yMin(), 0) );
    polygon->push_back( osg::Vec3d(extent.bounds().xMax(), extent.bounds().yMin(), 0) );
    polygon->push_back( osg::Vec3d(extent.bounds().xMax(), extent.bounds().yMax(), 0) );
    polygon->push_back( osg::Vec3d(extent.bounds().xMin(), extent.bounds().yMax(), 0) );
    polygon->push_back( osg::Vec3d(extent.bounds().xMin(), extent.bounds().yMin(), 0) );
   
    osg::ref_ptr< Feature > feature = new Feature( polygon.get(), extent.getSRS()  );
    feature->set("location", filename );
    
    const SpatialReference* wgs84 = SpatialReference::create("epsg:4326");
    feature->transform( wgs84 );

    return _features->insertFeature( feature.get() );    
    return true;
}
    osg::HeightField* createHeightField( const TileKey&        key,
                                         ProgressCallback*     progress)
    {
        if (key.getLevelOfDetail() > _maxDataLevel)
        {
            //OE_NOTICE << "Reached maximum data resolution key=" << key.getLevelOfDetail() << " max=" << _maxDataLevel <<  std::endl;
            return NULL;
        }

        int tileSize = _options.tileSize().value();

        //Allocate the heightfield
        osg::ref_ptr<osg::HeightField> hf = new osg::HeightField;
        hf->allocate(tileSize, tileSize);
        for (unsigned int i = 0; i < hf->getHeightList().size(); ++i) hf->getHeightList()[i] = NO_DATA_VALUE;

	    if (intersects(key))
        {
            //Get the extents of the tile
            double xmin, ymin, xmax, ymax;
            key.getExtent().getBounds(xmin, ymin, xmax, ymax);

            const SpatialReference* featureSRS = _features->getFeatureProfile()->getSRS();
            GeoExtent extentInFeatureSRS = key.getExtent().transform( featureSRS );

            const SpatialReference* keySRS = key.getProfile()->getSRS();
            
            // populate feature list
            // assemble a spatial query. It helps if your features have a spatial index.
            Query query;
            query.bounds() = extentInFeatureSRS.bounds();

		    FeatureList featureList;
            osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor(query);
            while ( cursor.valid() && cursor->hasMore() )
            {
                Feature* f = cursor->nextFeature();
                if ( f && f->getGeometry() )
                    featureList.push_back(f);
            }

            // We now have a feature list in feature SRS.

            bool transformRequired = !keySRS->isHorizEquivalentTo(featureSRS);
		    
			if (!featureList.empty())
			{
				// Iterate over the output heightfield and sample the data that was read into it.
				double dx = (xmax - xmin) / (tileSize-1);
				double dy = (ymax - ymin) / (tileSize-1);

				for (int c = 0; c < tileSize; ++c)
				{
					double geoX = xmin + (dx * (double)c);
					for (int r = 0; r < tileSize; ++r)
					{
						double geoY = ymin + (dy * (double)r);

						float h = NO_DATA_VALUE;

						for (FeatureList::iterator f = featureList.begin(); f != featureList.end(); ++f)
						{
							osgEarth::Symbology::Polygon* boundary = dynamic_cast<osgEarth::Symbology::Polygon*>((*f)->getGeometry());

							if (!boundary)
							{
								OE_WARN << LC << "NOT A POLYGON" << std::endl;
							}
							else
							{
								GeoPoint geo(keySRS, geoX, geoY, 0.0, ALTMODE_ABSOLUTE);

                                if ( transformRequired )
                                    geo = geo.transform(featureSRS);

								if ( boundary->contains2D(geo.x(), geo.y()) )
								{
                                    h = (*f)->getDouble(_options.attr().value());

                                    if ( keySRS->isGeographic() )
                                    {                              
                                        // for a round earth, must adjust the final elevation accounting for the
                                        // curvature of the earth; so we have to adjust it in the feature boundary's
                                        // local tangent plane.
                                        Bounds bounds = boundary->getBounds();
                                        GeoPoint anchor( featureSRS, bounds.center().x(), bounds.center().y(), h, ALTMODE_ABSOLUTE );
                                        if ( transformRequired )
                                            anchor = anchor.transform(keySRS);

                                        // For transforming between ECEF and local tangent plane:
                                        osg::Matrix localToWorld, worldToLocal;
                                        anchor.createLocalToWorld(localToWorld);
                                        worldToLocal.invert( localToWorld );

                                        // Get the ECEF location of the anchor point:
                                        osg::Vec3d ecef;
                                        geo.toWorld( ecef );

                                        // Move it into Local Tangent Plane coordinates:
                                        osg::Vec3d local = ecef * worldToLocal;

                                        // Reset the Z to zero, since the LTP is centered on the "h" elevation:
                                        local.z() = 0.0;

                                        // Back into ECEF:
                                        ecef = local * localToWorld;

                                        // And back into lat/long/alt:
                                        geo.fromWorld( geo.getSRS(), ecef);

                                        h = geo.z();
                                    }
									break;
								}
							}
						}

						hf->setHeight(c, r, h-0.1);
					}
				}
			}	
        }
        return hf.release();
    }
Exemplo n.º 6
0
bool
FeatureTileSource::queryAndRenderFeaturesForStyle(const Style&     style,
                                                  const Query&     query,
                                                  osg::Referenced* data,
                                                  const GeoExtent& imageExtent,
                                                  osg::Image*      out_image)
{   
    // first we need the overall extent of the layer:
    const GeoExtent& featuresExtent = getFeatureSource()->getFeatureProfile()->getExtent();
    
    // convert them both to WGS84, intersect the extents, and convert back.
    GeoExtent featuresExtentWGS84 = featuresExtent.transform( featuresExtent.getSRS()->getGeographicSRS() );
    GeoExtent imageExtentWGS84 = imageExtent.transform( featuresExtent.getSRS()->getGeographicSRS() );
    GeoExtent queryExtentWGS84 = featuresExtentWGS84.intersectionSameSRS( imageExtentWGS84 );
    if ( queryExtentWGS84.isValid() )
    {
        GeoExtent queryExtent = queryExtentWGS84.transform( featuresExtent.getSRS() );

        // incorporate the image extent into the feature query for this style:
        Query localQuery = query;
        localQuery.bounds() = 
            query.bounds().isSet() ? query.bounds()->unionWith( queryExtent.bounds() ) :
            queryExtent.bounds();

        // query the feature source:
        osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor( localQuery );

        // now copy the resulting feature set into a list, converting the data
        // types along the way if a geometry override is in place:
        FeatureList cellFeatures;
        while( cursor.valid() && cursor->hasMore() )
        {
            Feature* feature = cursor->nextFeature();
            Geometry* geom = feature->getGeometry();
            if ( geom )
            {
                // apply a type override if requested:
                if (_options.geometryTypeOverride().isSet() &&
                    _options.geometryTypeOverride() != geom->getComponentType() )
                {
                    geom = geom->cloneAs( _options.geometryTypeOverride().value() );
                    if ( geom )
                        feature->setGeometry( geom );
                }
            }
            if ( geom )
            {
                cellFeatures.push_back( feature );
            }
        }

        //OE_NOTICE
        //    << "Rendering "
        //    << cellFeatures.size()
        //    << " features in ("
        //    << queryExtent.toString() << ")"
        //    << std::endl;

        return renderFeaturesForStyle( style, cellFeatures, data, imageExtent, out_image );
    }
    else
    {
        return false;
    }
}
Exemplo n.º 7
0
FeatureCursorOGR::FeatureCursorOGR(OGRDataSourceH              dsHandle,
                                   OGRLayerH                   layerHandle,
                                   const FeatureSource*        source,
                                   const FeatureProfile*       profile,
                                   const Symbology::Query&     query,
                                   const FeatureFilterList&    filters) :
_source           ( source ),
_dsHandle         ( dsHandle ),
_layerHandle      ( layerHandle ),
_resultSetHandle  ( 0L ),
_spatialFilter    ( 0L ),
_query            ( query ),
_chunkSize        ( 500 ),
_nextHandleToQueue( 0L ),
_resultSetEndReached(false),
_profile          ( profile ),
_filters          ( filters )
{
    {
        OGR_SCOPED_LOCK;

        std::string expr;
        std::string from = OGR_FD_GetName( OGR_L_GetLayerDefn( _layerHandle ));        
        
        
        std::string driverName = OGR_Dr_GetName( OGR_DS_GetDriver( dsHandle ) );             
        // Quote the layer name if it is a shapefile, so we can handle any weird filenames like those with spaces or hyphens.
        // Or quote any layers containing spaces for PostgreSQL
        if (driverName == "ESRI Shapefile" || driverName == "VRT" ||
            from.find(" ") != std::string::npos)
        {
            std::string delim = "\"";
            from = delim + from + delim;
        }

        if ( _query.expression().isSet() )
        {
            // build the SQL: allow the Query to include either a full SQL statement or
            // just the WHERE clause.
            expr = _query.expression().value();

            // if the expression is just a where clause, expand it into a complete SQL expression.
            std::string temp = osgEarth::toLower(expr);

            if ( temp.find( "select" ) != 0 )
            {
                std::stringstream buf;
                buf << "SELECT * FROM " << from << " WHERE " << expr;
                std::string bufStr;
                bufStr = buf.str();
                expr = bufStr;
            }
        }
        else
        {
            std::stringstream buf;
            buf << "SELECT * FROM " << from;
            expr = buf.str();
        }

        //Include the order by clause if it's set
        if (_query.orderby().isSet())
        {                     
            std::string orderby = _query.orderby().value();
            
            std::string temp = osgEarth::toLower(orderby);

            if ( temp.find( "order by" ) != 0 )
            {                
                std::stringstream buf;
                buf << "ORDER BY " << orderby;                
                std::string bufStr;
                bufStr = buf.str();
                orderby = buf.str();
            }
            expr += (" " + orderby );
        }

        // if the tilekey is set, convert it to feature profile coords
        if ( _query.tileKey().isSet() && !_query.bounds().isSet() && profile )
        {
            GeoExtent localEx = _query.tileKey()->getExtent().transform( profile->getSRS() );
            _query.bounds() = localEx.bounds();
        }

        // if there's a spatial extent in the query, build the spatial filter:
        if ( _query.bounds().isSet() )
        {
            OGRGeometryH ring = OGR_G_CreateGeometry( wkbLinearRing );
            OGR_G_AddPoint(ring, _query.bounds()->xMin(), _query.bounds()->yMin(), 0 );
            OGR_G_AddPoint(ring, _query.bounds()->xMin(), _query.bounds()->yMax(), 0 );
            OGR_G_AddPoint(ring, _query.bounds()->xMax(), _query.bounds()->yMax(), 0 );
            OGR_G_AddPoint(ring, _query.bounds()->xMax(), _query.bounds()->yMin(), 0 );
            OGR_G_AddPoint(ring, _query.bounds()->xMin(), _query.bounds()->yMin(), 0 );

            _spatialFilter = OGR_G_CreateGeometry( wkbPolygon );
            OGR_G_AddGeometryDirectly( _spatialFilter, ring ); 
            // note: "Directly" above means _spatialFilter takes ownership if ring handle
        }


        OE_DEBUG << LC << "SQL: " << expr << std::endl;
        _resultSetHandle = OGR_DS_ExecuteSQL( _dsHandle, expr.c_str(), _spatialFilter, 0L );

        if ( _resultSetHandle )
        {
            OGR_L_ResetReading( _resultSetHandle );
        }
    }

    readChunk();
}