osgEarth 2.1.1
Classes | Public Member Functions | Private Attributes

AGGLiteRasterizerTileSource Class Reference

Inheritance diagram for AGGLiteRasterizerTileSource:
Collaboration diagram for AGGLiteRasterizerTileSource:

List of all members.

Classes

struct  BuildData

Public Member Functions

 AGGLiteRasterizerTileSource (const TileSourceOptions &options)
osg::Referenced * createBuildData ()
bool preProcess (osg::Image *image, osg::Referenced *buildData)
bool renderFeaturesForStyle (const Style &style, const FeatureList &inFeatures, osg::Referenced *buildData, const GeoExtent &imageExtent, osg::Image *image)
bool postProcess (osg::Image *image, osg::Referenced *data)
virtual std::string getExtension () const

Private Attributes

const AGGLiteOptions _options
std::string _configPath

Detailed Description

Definition at line 54 of file AGGLiteRasterizerTileSource.cpp.


Constructor & Destructor Documentation

AGGLiteRasterizerTileSource::AGGLiteRasterizerTileSource ( const TileSourceOptions options) [inline]

Definition at line 57 of file AGGLiteRasterizerTileSource.cpp.

                                                                    : FeatureTileSource( options ),
        _options( options )
    {
        //nop
    }

Member Function Documentation

osg::Referenced* AGGLiteRasterizerTileSource::createBuildData ( ) [inline, virtual]

Creates an implementation-specific data object to be passed to buildNodeForStyle

Reimplemented from osgEarth::Features::FeatureTileSource.

Definition at line 69 of file AGGLiteRasterizerTileSource.cpp.

    {
        return new BuildData();
    }
virtual std::string AGGLiteRasterizerTileSource::getExtension ( ) const [inline, virtual]

Gets the preferred extension for this TileSource

Reimplemented from osgEarth::TileSource.

Definition at line 334 of file AGGLiteRasterizerTileSource.cpp.

    {
        return "png";
    }
bool AGGLiteRasterizerTileSource::postProcess ( osg::Image *  image,
osg::Referenced *  buildData 
) [inline, virtual]

Optional implementation hook to post-process an image tile after all calls to renderFeaturesForStyle() are complete.

Reimplemented from osgEarth::Features::FeatureTileSource.

Definition at line 322 of file AGGLiteRasterizerTileSource.cpp.

    {
                //convert from ABGR to RGBA
                unsigned char* pixel = image->data();
                for(int i=0; i<image->s()*image->t()*4; i+=4, pixel+=4)
                {
                        std::swap( pixel[0], pixel[3] );
                        std::swap( pixel[1], pixel[2] );
                }
        return true;
    }
bool AGGLiteRasterizerTileSource::preProcess ( osg::Image *  image,
osg::Referenced *  buildData 
) [inline, virtual]

Optional implementation hook to pre-process an image tile before any calls to renderFeaturesForStyle().

Reimplemented from osgEarth::Features::FeatureTileSource.

Definition at line 75 of file AGGLiteRasterizerTileSource.cpp.

    {
        agg::rendering_buffer rbuf( image->data(), image->s(), image->t(), image->s()*4 );
        agg::renderer<agg::span_abgr32> ren(rbuf);
        ren.clear(agg::rgba8(0,0,0,0));
        //ren.clear(agg::rgba8(255,255,255,0));
        return true;
    }
bool AGGLiteRasterizerTileSource::renderFeaturesForStyle ( const Style style,
const FeatureList features,
osg::Referenced *  buildData,
const GeoExtent imageExtent,
osg::Image *  out_image 
) [inline, virtual]

Creates OSG graph(s) representing the specified feature list.

Parameters:
styleStyling information for the feature geometry
featuresFeatures to render
buildDataImplementation-specific build data (from createBuildData)
out_imagePre-allocated image to which the implementation would render.
Returns:
true if the rendering succeeded, false if the out_image did not change.

Reimplemented from osgEarth::Features::FeatureTileSource.

Definition at line 85 of file AGGLiteRasterizerTileSource.cpp.

    {
        // local copy of the features that we can process
        FeatureList features = inFeatures;

        BuildData* bd = static_cast<BuildData*>( buildData );

        // A processing context to use with the filters:
        FilterContext context;
        context.profile() = getFeatureSource()->getFeatureProfile();

        const LineSymbol* masterLine = style.getSymbol<LineSymbol>();
        const PolygonSymbol* masterPoly = style.getSymbol<PolygonSymbol>();

        //bool embeddedStyles = getFeatureSource()->hasEmbeddedStyles();

        // if only a line symbol exists, and there are polygons in the mix, draw them
        // as outlines (line rings).
        //OE_INFO << LC << "Line Symbol = " << (masterLine == 0L ? "null" : masterLine->getConfig().toString()) << std::endl;
        //OE_INFO << LC << "Poly SYmbol = " << (masterPoly == 0L ? "null" : masterPoly->getConfig().toString()) << std::endl;

        //bool convertPolysToRings = poly == 0L && line != 0L;
        //if ( convertPolysToRings )
        //    OE_INFO << LC << "No PolygonSymbol; will draw polygons to rings" << std::endl;

        // initialize:
        double xmin = imageExtent.xMin();
        double ymin = imageExtent.yMin();
        //double s = (double)image->s();
        //double t = (double)image->t();
        double xf = (double)image->s() / imageExtent.width();
        double yf = (double)image->t() / imageExtent.height();

        // strictly speaking we should iterate over the features and buffer each one that's a line,
        // rather then checking for the existence of a LineSymbol.
        FeatureList linesToBuffer;
        for(FeatureList::iterator i = features.begin(); i != features.end(); i++)
        {
            Feature* feature = i->get();
            Geometry* geom = feature->getGeometry();

            if ( geom )
            {
                // check for an embedded style:
                const LineSymbol* line = feature->style().isSet() ? 
                    feature->style()->getSymbol<LineSymbol>() : masterLine;

                const PolygonSymbol* poly =
                    feature->style().isSet() ? feature->style()->getSymbol<PolygonSymbol>() : masterPoly;

                // if we have polygons but only a LineSymbol, draw the poly as a line.
                if ( geom->getComponentType() == Geometry::TYPE_POLYGON )
                {
                    if ( !poly && line )
                    {
                        Feature* outline = new Feature( *feature );
                        geom = geom->cloneAs( Geometry::TYPE_RING );
                        outline->setGeometry( geom );
                        *i = outline;
                        feature = outline;
                    }
                    //TODO: fix to enable outlined polys. doesn't work, not sure why -gw
                    //else if ( poly && line )
                    //{
                    //    Feature* outline = new Feature();
                    //    geom = geom->cloneAs( Geometry::TYPE_LINESTRING );
                    //    outline->setGeometry( geom );
                    //    features.push_back( outline );
                    //}
                }

                bool needsBuffering =
                    geom->getComponentType() == Geometry::TYPE_LINESTRING || 
                    geom->getComponentType() == Geometry::TYPE_RING;

                if ( needsBuffering )
                {
                    linesToBuffer.push_back( feature );
                }
            }
        }

        if ( linesToBuffer.size() > 0 )
        {
            //We are buffering in the features native extent, so we need to use the transform extent to get the proper "resolution" for the image
            GeoExtent transformedExtent = imageExtent.transform(context.profile()->getSRS());

            double trans_xf = (double)image->s() / transformedExtent.width();
            double trans_yf = (double)image->t() / transformedExtent.height();

            // resolution of the image (pixel extents):
            double xres = 1.0/trans_xf;
            double yres = 1.0/trans_yf;

            // downsample the line data so that it is no higher resolution than to image to which
            // we intend to rasterize it. If you don't do this, you run the risk of the buffer 
            // operation taking forever on very high-res input data.
            if ( _options.optimizeLineSampling() == true )
            {
                ResampleFilter resample;
                resample.minLength() = osg::minimum( xres, yres );
                context = resample.push( linesToBuffer, context );
            }

            // now run the buffer operation on all lines:
            BufferFilter buffer;
            float lineWidth = 0.5;
            if ( masterLine )
            {
                buffer.capStyle() = masterLine->stroke()->lineCap().value();

                if ( masterLine->stroke()->width().isSet() )
                    lineWidth = masterLine->stroke()->width().value();
            }

            // "relative line size" means that the line width is expressed in (approx) pixels
            // rather than in map units
            if ( _options.relativeLineSize() == true )
                buffer.distance() = xres * lineWidth;
            else
                buffer.distance() = lineWidth;

            buffer.push( linesToBuffer, context );
        }

        // First, transform the features into the map's SRS:
        TransformFilter xform( imageExtent.getSRS() );
        xform.setLocalizeCoordinates( false );
        context = xform.push( features, context );

        // set up the AGG renderer:
        agg::rendering_buffer rbuf( image->data(), image->s(), image->t(), image->s()*4 );

        // Create the renderer and the rasterizer
        agg::renderer<agg::span_abgr32> ren(rbuf);
        agg::rasterizer ras;

        // Setup the rasterizer
        ras.gamma(1.3);
        ras.filling_rule(agg::fill_even_odd);

        GeoExtent cropExtent = GeoExtent(imageExtent);
        cropExtent.scale(1.1, 1.1);

        osg::ref_ptr<Symbology::Polygon> cropPoly = new Symbology::Polygon( 4 );
        cropPoly->push_back( osg::Vec3d( cropExtent.xMin(), cropExtent.yMin(), 0 ));
        cropPoly->push_back( osg::Vec3d( cropExtent.xMax(), cropExtent.yMin(), 0 ));
        cropPoly->push_back( osg::Vec3d( cropExtent.xMax(), cropExtent.yMax(), 0 ));
        cropPoly->push_back( osg::Vec3d( cropExtent.xMin(), cropExtent.yMax(), 0 ));

        double lineWidth = 1.0;
        if ( masterLine )
            lineWidth = (double)masterLine->stroke()->width().value();

        osg::Vec4 color = osg::Vec4(1, 1, 1, 1);
        if ( masterLine )
            color = masterLine->stroke()->color();

        // render the features
        for(FeatureList::iterator i = features.begin(); i != features.end(); i++)
        {
            Feature* feature = i->get();
            //bool first = bd->_pass == 0 && i == features.begin();

            Geometry* geometry = feature->getGeometry();

            osg::ref_ptr< Geometry > croppedGeometry;
            if ( ! geometry->crop( cropPoly.get(), croppedGeometry ) )
                continue;

            // set up a default color:
            osg::Vec4 c = color;
            unsigned int a = (unsigned int)(127+(c.a()*255)/2); // scale alpha up
            agg::rgba8 fgColor( (unsigned int)(c.r()*255), (unsigned int)(c.g()*255), (unsigned int)(c.b()*255), a );

            GeometryIterator gi( croppedGeometry.get() );
            while( gi.hasMore() )
            {
                c = color;
                Geometry* g = gi.next();
            
                const LineSymbol* line = feature->style().isSet() ? 
                    feature->style()->getSymbol<LineSymbol>() : masterLine;

                const PolygonSymbol* poly =
                    feature->style().isSet() ? feature->style()->getSymbol<PolygonSymbol>() : masterPoly;

                if (g->getType() == Geometry::TYPE_RING || g->getType() == Geometry::TYPE_LINESTRING)
                {
                    if ( line )
                        c = line->stroke()->color();
                    else if ( poly )
                        c = poly->fill()->color();
                }

                else if ( g->getType() == Geometry::TYPE_POLYGON )
                {
                    if ( poly )
                        c = poly->fill()->color();
                    else if ( line )
                        c = line->stroke()->color();
                }

                a = 127+(c.a()*255)/2; // scale alpha up
                fgColor = agg::rgba8( (unsigned int)(c.r()*255), (unsigned int)(c.g()*255), (unsigned int)(c.b()*255), a );

                ras.filling_rule( agg::fill_even_odd );
                for( Geometry::iterator p = g->begin(); p != g->end(); p++ )
                {
                    const osg::Vec3d& p0 = *p;
                    double x0 = xf*(p0.x()-xmin);
                    double y0 = yf*(p0.y()-ymin);

                    //const osg::Vec3d& p1 = p+1 != g->end()? *(p+1) : g->front();
                    //double x1 = xf*(p1.x()-xmin);
                    //double y1 = yf*(p1.y()-ymin);

                    if ( p == g->begin() )
                        ras.move_to_d( x0, y0 );
                    else
                        ras.line_to_d( x0, y0 );
                }
            }
            ras.render(ren, fgColor);
            ras.reset();
        }

        bd->_pass++;
        return true;            
    }

Here is the call graph for this function:


Member Data Documentation

Definition at line 341 of file AGGLiteRasterizerTileSource.cpp.

Reimplemented from osgEarth::Features::FeatureTileSource.

Definition at line 340 of file AGGLiteRasterizerTileSource.cpp.


The documentation for this class was generated from the following file:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines