osgEarth 2.1.1
Public Member Functions | Protected Member Functions | Protected Attributes

osgEarth::Features::BuildGeometryFilter Class Reference

Inheritance diagram for osgEarth::Features::BuildGeometryFilter:
Collaboration diagram for osgEarth::Features::BuildGeometryFilter:

List of all members.

Public Member Functions

 BuildGeometryFilter (const Style &style=Style())
osg::Node * push (FeatureList &input, FilterContext &context)
const StylegetStyle ()
void setStyle (const Style &s)
optional< double > & maxGranularity ()
const optional< double > & maxGranularity () const
optional< GeoInterpolation > & geoInterp ()
const optional
< GeoInterpolation > & 
geoInterp () const
optional< bool > & mergeGeometry ()
const optional< bool > & mergeGeometry () const
optional< StringExpression > & featureName ()
const optional
< StringExpression > & 
featureName () const

Protected Member Functions

void reset ()
bool process (FeatureList &input, const FilterContext &context)

Protected Attributes

osg::ref_ptr< osg::Node > _result
osg::ref_ptr< osg::Geode > _geode
Style _style
optional< double > _maxAngle_deg
optional< GeoInterpolation_geoInterp
optional< bool > _mergeGeometry
optional< StringExpression_featureNameExpr
bool _hasPoints
bool _hasLines
bool _hasPolygons

Detailed Description

Builds geometry from a stream of input features.

Definition at line 38 of file BuildGeometryFilter.


Constructor & Destructor Documentation

BuildGeometryFilter::BuildGeometryFilter ( const Style style = Style())

Definition at line 48 of file BuildGeometryFilter.cpp.

                                                             :
_style        ( style ),
_maxAngle_deg ( 5.0 ),
_geoInterp    ( GEOINTERP_RHUMB_LINE ),
_mergeGeometry( false )
{
    reset();
}

Here is the call graph for this function:


Member Function Documentation

optional<StringExpression>& osgEarth::Features::BuildGeometryFilter::featureName ( ) [inline]

Sets an expression to evaluate for setting the name of a Geometry. This only takes effect if mergeGeometry is false.

Definition at line 79 of file BuildGeometryFilter.

{ return _featureNameExpr; }

Here is the caller graph for this function:

const optional<StringExpression>& osgEarth::Features::BuildGeometryFilter::featureName ( ) const [inline]

Definition at line 80 of file BuildGeometryFilter.

{ return _featureNameExpr; }
optional<GeoInterpolation>& osgEarth::Features::BuildGeometryFilter::geoInterp ( ) [inline]

The algorithm to use when interpolating between geodetic locations. The default is GEOINTERP_RHUMBLINE.

Definition at line 64 of file BuildGeometryFilter.

{ return _geoInterp; }

Here is the caller graph for this function:

const optional<GeoInterpolation>& osgEarth::Features::BuildGeometryFilter::geoInterp ( ) const [inline]

Definition at line 65 of file BuildGeometryFilter.

{ return _geoInterp; }
const Style& osgEarth::Features::BuildGeometryFilter::getStyle ( ) [inline]

The style to apply to feature geometry

Definition at line 47 of file BuildGeometryFilter.

{ return _style; }
const optional<double>& osgEarth::Features::BuildGeometryFilter::maxGranularity ( ) const [inline]

Definition at line 58 of file BuildGeometryFilter.

{ return _maxAngle_deg; }
optional<double>& osgEarth::Features::BuildGeometryFilter::maxGranularity ( ) [inline]

For geocentric data, sets the granularity of edges created by the filter. This is the maximum angle (in degrees) between the vectors representing two geocentric points comprising an edge. Since large polygons won't naturally conform to the ellipsoid very well, this setting lets you specify a minimum edge size so that they will break down and conform better.

Definition at line 57 of file BuildGeometryFilter.

{ return _maxAngle_deg; }

Here is the caller graph for this function:

optional<bool>& osgEarth::Features::BuildGeometryFilter::mergeGeometry ( ) [inline]

Whether to merge the geometries from mutliple features together. Doing this can help performance by batching geometries together. The downside will be that individual geometries are no longer addressable in the scene graph. Default is FALSE.

Definition at line 72 of file BuildGeometryFilter.

{ return _mergeGeometry; }

Here is the caller graph for this function:

const optional<bool>& osgEarth::Features::BuildGeometryFilter::mergeGeometry ( ) const [inline]

Definition at line 73 of file BuildGeometryFilter.

{ return _mergeGeometry; }
bool BuildGeometryFilter::process ( FeatureList input,
const FilterContext context 
) [protected]

Definition at line 68 of file BuildGeometryFilter.cpp.

{
    bool makeECEF = context.getSession()->getMapInfo().isGeocentric();
    const SpatialReference* srs = context.extent()->getSRS();

    for( FeatureList::iterator f = features.begin(); f != features.end(); ++f )
    {
        Feature* input = f->get();

        GeometryIterator parts( input->getGeometry(), false );
        while( parts.hasMore() )
        {
            Geometry* part = parts.next();
            
            osg::PrimitiveSet::Mode primMode = osg::PrimitiveSet::POINTS;

            const Style& myStyle = input->style().isSet() ? *input->style() : _style;

            osg::Vec4f color = osg::Vec4(1,1,1,1);
            bool tessellatePolys = true;

            bool setWidth = input->style().isSet(); // otherwise it will be set globally, we assume
            float width = 1.0f;

            switch( part->getType() )
            {
            case Geometry::TYPE_POINTSET:
                {
                    _hasPoints = true;
                    primMode = osg::PrimitiveSet::POINTS;
                    const PointSymbol* point = myStyle.getSymbol<PointSymbol>();
                    if (point)
                    {
                        color = point->fill()->color();
                    }
                }
                break;

            case Geometry::TYPE_LINESTRING:
                {
                    _hasLines = true;
                    primMode = osg::PrimitiveSet::LINE_STRIP;
                    const LineSymbol* lineSymbol = myStyle.getSymbol<LineSymbol>();
                    if (lineSymbol)
                    {
                        color = lineSymbol->stroke()->color();
                        width = lineSymbol->stroke()->width().isSet() ? *lineSymbol->stroke()->width() : 1.0f;
                    }
                }
                break;

            case Geometry::TYPE_RING:
                {
                    _hasLines = true;
                    primMode = osg::PrimitiveSet::LINE_LOOP;
                    const LineSymbol* lineSymbol = myStyle.getSymbol<LineSymbol>();
                    if (lineSymbol)
                    {
                        color = lineSymbol->stroke()->color();
                        width = lineSymbol->stroke()->width().isSet() ? *lineSymbol->stroke()->width() : 1.0f;
                    }
                }
                break;

            case Geometry::TYPE_POLYGON:
                {
                    primMode = osg::PrimitiveSet::LINE_LOOP; // loop will tessellate into polys
                    const PolygonSymbol* poly = myStyle.getSymbol<PolygonSymbol>();
                    if (poly)
                    {
                        _hasPolygons = true;
                        color = poly->fill()->color();
                    }
                    else
                    {
                        // if we have a line symbol and no polygon symbol, draw as an outline.
                        _hasLines = true;
                        const LineSymbol* line = myStyle.getSymbol<LineSymbol>();
                        if ( line )
                        {
                            color = line->stroke()->color();
                            width = line->stroke()->width().isSet() ? *line->stroke()->width() : 1.0f;
                            tessellatePolys = false;
                        }
                    }
                }
                break;
            }
            
            osg::Geometry* osgGeom = new osg::Geometry();

            if ( _featureNameExpr.isSet() )
            {
                const std::string& name = input->eval( _featureNameExpr.mutable_value() );
                osgGeom->setName( name );
            }

            // NOTE: benchmarking reveals VBOs to be much slower (for static data, at least)
            //osgGeom->setUseVertexBufferObjects( true );
            //osgGeom->setUseDisplayList( false );

            if ( setWidth && width != 1.0f )
            {
                osgGeom->getOrCreateStateSet()->setAttributeAndModes(
                    new osg::LineWidth( width ), osg::StateAttribute::ON );
            }

            if (_hasLines)
            {
                const LineSymbol* line = myStyle.getSymbol<LineSymbol>();
                if (line && line->stroke().isSet() && line->stroke()->stipple().isSet())
                {
                    osg::LineStipple* lineStipple = new osg::LineStipple;
                    lineStipple->setPattern( *line->stroke()->stipple() );            
                    osgGeom->getOrCreateStateSet()->setAttributeAndModes( lineStipple, osg::StateAttribute::ON );
                }
            }
            
            if (part->getType() == Geometry::TYPE_POLYGON && static_cast<Polygon*>(part)->getHoles().size() > 0 )
            {
                Polygon* poly = static_cast<Polygon*>(part);
                int totalPoints = poly->getTotalPointCount();
                osg::Vec3Array* allPoints; // = new osg::Vec3Array( totalPoints );

                if ( makeECEF )
                {
                    allPoints = new osg::Vec3Array();
                    ECEF::transformAndLocalize( part->asVector(), allPoints, srs, _world2local );
                }
                else
                {
                    allPoints = new osg::Vec3Array( totalPoints );
                    std::copy( part->begin(), part->end(), allPoints->begin() );
                }
                osgGeom->addPrimitiveSet( new osg::DrawArrays( primMode, 0, part->size() ) );

                int offset = part->size();

                for( RingCollection::const_iterator h = poly->getHoles().begin(); h != poly->getHoles().end(); ++h )
                {
                    Geometry* hole = h->get();
                    if ( hole->isValid() )
                    {
                        if ( makeECEF )
                            ECEF::transformAndLocalize( hole->asVector(), allPoints, srs, _world2local );
                        else
                            std::copy( hole->begin(), hole->end(), allPoints->begin() + offset );

                        osgGeom->addPrimitiveSet( new osg::DrawArrays( primMode, offset, hole->size() ) );
                        offset += hole->size();
                    }
                }
                osgGeom->setVertexArray( allPoints );
            }
            else
            {
                if ( makeECEF )
                {
                    osg::Vec3Array* newPart = new osg::Vec3Array();
                    ECEF::transformAndLocalize( part->asVector(), newPart, srs, _world2local );
                    osgGeom->setVertexArray( newPart );
                }
                else
                {
                    osgGeom->setVertexArray( part->toVec3Array() );
                }
                osgGeom->addPrimitiveSet( new osg::DrawArrays( primMode, 0, part->size() ) );
            }

            // tessellate all polygon geometries. Tessellating each geometry separately
            // with TESS_TYPE_GEOMETRY is much faster than doing the whole bunch together
            // using TESS_TYPE_DRAWABLE.

            if ( part->getType() == Geometry::TYPE_POLYGON && tessellatePolys )
            {
                osgUtil::Tessellator tess;
                //tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_DRAWABLE );
                //tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_ODD );
                tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY );
                tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_POSITIVE );

                tess.retessellatePolygons( *osgGeom );

                // the tessellator results in a collection of trifans, strips, etc. This step will
                // consolidate those into one (or more if necessary) GL_TRIANGLES primitive.
                //NOTE: this now happens elsewhere 
                //MeshConsolidator::run( *osgGeom );

                // mark this geometry as DYNAMIC because otherwise the OSG optimizer will destroy it.
                //osgGeom->setDataVariance( osg::Object::DYNAMIC );
            }

            if ( context.getSession()->getMapInfo().isGeocentric() && part->getType() != Geometry::TYPE_POINTSET )
//            if ( context.isGeocentric() && part->getType() != Geometry::TYPE_POINTSET )
            {
                double threshold = osg::DegreesToRadians( *_maxAngle_deg );

                MeshSubdivider ms( _world2local, _local2world ); //context.referenceFrame(), context.inverseReferenceFrame() );
                //ms.setMaxElementsPerEBO( INT_MAX );
                if ( input->geoInterp().isSet() )
                    ms.run( *osgGeom, threshold, *input->geoInterp() );
                else
                    ms.run( *osgGeom, threshold, *_geoInterp );
            }

            // NOTE! per-vertex colors makes the optimizer destroy the geometry....
            osg::Vec4Array* colors = new osg::Vec4Array(1);
            (*colors)[0] = color;
            osgGeom->setColorArray( colors );
            osgGeom->setColorBinding( osg::Geometry::BIND_OVERALL );

            // add the part to the geode.
            _geode->addDrawable( osgGeom );
        }
    }
    
    return true;
}

Here is the call graph for this function:

Here is the caller graph for this function:

osg::Node * BuildGeometryFilter::push ( FeatureList input,
FilterContext context 
) [virtual]

Pushes a list of features through the filter.

Implements osgEarth::Features::FeaturesToNodeFilter.

Definition at line 288 of file BuildGeometryFilter.cpp.

{
    reset();

    computeLocalizers( context );

    bool ok = process( input, context );

    // convert all geom to triangles and consolidate into minimal set of Geometries
    if ( !_featureNameExpr.isSet() )
    {
        MeshConsolidator::run( *_geode.get() );
    }

    osg::Node* result = 0L;

    if ( ok )
    {
        if ( !_style.empty() && _geode.valid() )
        {
            // could optimize this to only happen is lines or points were created ..
            const LineSymbol* lineSymbol = _style.getSymbol<LineSymbol>();
            float size = 1.0;
            if (lineSymbol)
                size = lineSymbol->stroke()->width().value();

            _geode->getOrCreateStateSet()->setAttribute( new osg::Point(size), osg::StateAttribute::ON );
            _geode->getOrCreateStateSet()->setAttribute( new osg::LineWidth(size), osg::StateAttribute::ON );

            const PointSymbol* pointSymbol = _style.getSymbol<PointSymbol>();
            if ( pointSymbol && pointSymbol->size().isSet() )
                _geode->getOrCreateStateSet()->setAttribute( 
                    new osg::Point( *pointSymbol->size() ), osg::StateAttribute::ON );
        }

        result = delocalize( _geode.release() );
    }
    else
    {
        result = 0L;
    }

    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void BuildGeometryFilter::reset ( ) [protected]

Definition at line 58 of file BuildGeometryFilter.cpp.

{
    _result = 0L;
    _geode = new osg::Geode();
    _hasLines = false;
    _hasPoints = false;
    _hasPolygons = false;
}

Here is the caller graph for this function:

void osgEarth::Features::BuildGeometryFilter::setStyle ( const Style s) [inline]

Definition at line 48 of file BuildGeometryFilter.

{ _style = s; }

Here is the caller graph for this function:


Member Data Documentation

Definition at line 89 of file BuildGeometryFilter.

osg::ref_ptr<osg::Geode> osgEarth::Features::BuildGeometryFilter::_geode [protected]

Definition at line 84 of file BuildGeometryFilter.

Definition at line 87 of file BuildGeometryFilter.

Definition at line 91 of file BuildGeometryFilter.

Definition at line 90 of file BuildGeometryFilter.

Definition at line 92 of file BuildGeometryFilter.

Definition at line 86 of file BuildGeometryFilter.

Definition at line 88 of file BuildGeometryFilter.

osg::ref_ptr<osg::Node> osgEarth::Features::BuildGeometryFilter::_result [protected]

Definition at line 83 of file BuildGeometryFilter.

Definition at line 85 of file BuildGeometryFilter.


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