osgEarth 2.1.1
Public Member Functions | Protected Attributes

anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory Class Reference

Inheritance diagram for anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory:
Collaboration diagram for anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory:

List of all members.

Public Member Functions

 StencilVolumeNodeFactory (const FeatureStencilModelOptions &options, int renderBinStart)
bool createOrUpdateNode (FeatureCursor *cursor, const Style &style, const FilterContext &context, osg::ref_ptr< osg::Node > &node)
osg::Group * getOrCreateStyleGroup (const Style &style, Session *session)

Protected Attributes

const FeatureStencilModelOptions _options
int _renderBinStart
BuildData _buildData

Detailed Description

Definition at line 351 of file FeatureStencilModelSource.cpp.


Constructor & Destructor Documentation

anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory::StencilVolumeNodeFactory ( const FeatureStencilModelOptions options,
int  renderBinStart 
) [inline]

Definition at line 359 of file FeatureStencilModelSource.cpp.

            : _options(options),
              _buildData( renderBinStart )
        { }

Member Function Documentation

bool anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory::createOrUpdateNode ( FeatureCursor cursor,
const Style style,
const FilterContext context,
osg::ref_ptr< osg::Node > &  node 
) [inline, virtual]

Render (or update) a list of features into a node according to the specified style.

Implements osgEarth::Features::FeatureNodeFactory.

Definition at line 365 of file FeatureStencilModelSource.cpp.

        {
            const MapInfo& mi = context.getSession()->getMapInfo();
            
            // A processing context to use locally
            FilterContext cx = context;

            // make a working copy of the feature data.
            FeatureList featureList;
            cursor->fill( featureList );

            //for (FeatureList::const_iterator it = features.begin(); it != features.end(); ++it)
            //    featureList.push_back(osg::clone((*it).get(),osg::CopyOp::DEEP_COPY_ALL));

            // establish the extrusion distance for the stencil volumes
            double extrusionDistance = 1;
            double densificationThreshold = 1.0;
            if ( _options.extrusionDistance().isSet() )
            {
                extrusionDistance = *_options.extrusionDistance();
            }
            else
            {
                if ( mi.isGeocentric() )
                    extrusionDistance = 300000.0; // meters geocentric
                else if ( mi.getProfile()->getSRS()->isGeographic() )
                    extrusionDistance = 5.0; // degrees-as-meters
                else
                    extrusionDistance = 12000.0; // meters
            }

            densificationThreshold = *_options.densificationThreshold();

            // Scan the geometry to see if it includes line data, since that will require buffering:
            bool hasLines = false;
            for( FeatureList::const_iterator i = featureList.begin(); i != featureList.end(); ++i )
            {
                Feature* feature = (*i).get();
                Geometry* geom = feature->getGeometry();
                if ( geom && 
                     ( geom->getComponentType() == Geometry::TYPE_LINESTRING ||
                       geom->getComponentType() == Geometry::TYPE_RING ) )
                {
                    hasLines = true;
                    break;
                }
            }

            // If the geometry is lines, we need to buffer them before they will work with stenciling
            if ( hasLines )
            {
                const LineSymbol* line = style.getSymbol<LineSymbol>();
                if (line)
                {
                    BufferFilter buffer;
                    buffer.distance() = 0.5 * line->stroke()->width().value();
                    buffer.capStyle() = line->stroke()->lineCap().value();
                    cx = buffer.push( featureList, cx );
                }
            }

            // Transform them into the map's SRS, localizing the verts along the way:
            TransformFilter xform( mi.getProfile()->getSRS() );
            xform.setMakeGeocentric( mi.isGeocentric() );
            xform.setLocalizeCoordinates( !mi.isGeocentric() );
            cx = xform.push( featureList, cx );

            if ( mi.isGeocentric() )
            {
                // We need to make sure that on a round globe, the points are sampled such that
                // long segments follow the curvature of the earth. By the way, if a Buffer was
                // applied, that will also remove colinear segment points. Resample the points to 
                // achieve a usable tesselation.
                ResampleFilter resample;
                resample.maxLength() = densificationThreshold;
                resample.minLength() = 0.0;
                resample.perturbationThreshold() = 0.1;
                cx = resample.push( featureList, cx );
            }

            // Extrude and cap the geometry in both directions to build a stencil volume:
            osg::Group* volumes = 0L;

            for( FeatureList::iterator i = featureList.begin(); i != featureList.end(); ++i )
            {
                Feature* feature = (*i).get();
                Geometry* geom = feature->getGeometry();
                osg::Node* volume = createVolume( geom, -extrusionDistance, extrusionDistance * 2.0, cx );

                if ( volume )
                {
                    if ( !volumes )
                        volumes = new osg::Group();
                    volumes->addChild( volume );
                }
            }

            if ( volumes )
            {
                // Resolve the localizing reference frame if necessary:
                if ( cx.hasReferenceFrame() )
                {
                    osg::MatrixTransform* xform = new osg::MatrixTransform( cx.inverseReferenceFrame() );
                    xform->addChild( volumes );
                    volumes = xform;
                }

                // Apply an LOD if required:
                if ( _options.minRange().isSet() || _options.maxRange().isSet() )
                {
                    osg::LOD* lod = new osg::LOD();
                    lod->addChild( volumes, _options.minRange().value(), _options.maxRange().value() );
                    volumes = lod;
                }

                // Add the volumes to the appropriate style group.
                StencilVolumeNode* styleNode = dynamic_cast<StencilVolumeNode*>( getOrCreateStyleGroup( style, cx.getSession() ) );
                styleNode->addVolumes( volumes );
            }

            node = 0L; // always return null, since we added our geom to the style group.
            return volumes != 0L;
        }

Here is the call graph for this function:

osg::Group* anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory::getOrCreateStyleGroup ( const Style style,
Session session 
) [inline, virtual]

Creates a group that will contain all the geometry corresponding to a given style. The subclass has the option of overriding this in order to create a custom implementation.

Reimplemented from osgEarth::Features::FeatureNodeFactory.

Definition at line 494 of file FeatureStencilModelSource.cpp.

        {
            if ( _options.showVolumes() == true )
            {
                return new osg::Group();
            }
            else
            {
                StencilVolumeNode* styleNode = 0L;
                if ( !_buildData.getStyleNode(style.getName(), styleNode, true) )
                {
                    // did not find; write-lock it and try again (double-check pattern)
                    Threading::ScopedWriteLock exclusiveLock( _buildData._mutex );

                    if ( !_buildData.getStyleNode(style.getName(), styleNode, false) )
                    {
                        OE_INFO << LC << "Create style group \"" << style.getName() << "\"" << std::endl;

                        styleNode = new StencilVolumeNode( *_options.mask(), *_options.inverted() );

                        if ( _options.mask() == false )
                        {
                            osg::Vec4f maskColor = osg::Vec4(1,1,0,1);

                            if (/*hasLines &&*/ style.getSymbol<LineSymbol>())
                            {
                                const LineSymbol* line = style.getSymbol<LineSymbol>();
                                maskColor = line->stroke()->color();
                            } 
                            else
                            {
                                const PolygonSymbol* poly = style.getSymbol<PolygonSymbol>();
                                if (poly)
                                    maskColor = poly->fill()->color();
                            }
                            styleNode->addChild( createColorNode(maskColor) );
                            
                            osg::StateSet* ss = styleNode->getOrCreateStateSet();

                            ss->setMode( GL_LIGHTING, _options.enableLighting() == true?
                                 osg::StateAttribute::ON | osg::StateAttribute::PROTECTED :
                                 osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
                        }

                        _buildData._renderBin = styleNode->setBaseRenderBin( _buildData._renderBin );
                        _buildData._styleGroups.push_back( BuildData::StyleGroup(style.getName(), styleNode) );
                    }
                }

                return styleNode;
            }
        }

Here is the call graph for this function:


Member Data Documentation

BuildData anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory::_buildData [protected]

Definition at line 356 of file FeatureStencilModelSource.cpp.

const FeatureStencilModelOptions anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory::_options [protected]

Definition at line 354 of file FeatureStencilModelSource.cpp.

int anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory::_renderBinStart [protected]

Definition at line 355 of file FeatureStencilModelSource.cpp.


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