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

osgEarth::Features::ScatterFilter Class Reference

Inheritance diagram for osgEarth::Features::ScatterFilter:
Collaboration diagram for osgEarth::Features::ScatterFilter:

List of all members.

Public Member Functions

 ScatterFilter ()
void setDensity (float value)
float getDensity () const
void setRandom (bool value)
bool getRandom () const
void setRandomSeed (unsigned value)
unsigned getRandomSeed () const
virtual FilterContext push (FeatureList &input, FilterContext &context)

Static Public Member Functions

static bool isSupported ()

Protected Member Functions

void polyScatter (const Geometry *input, const SpatialReference *inputSRS, const FilterContext &context, PointSet *output)
void lineScatter (const Geometry *input, const SpatialReference *inputSRS, const FilterContext &context, PointSet *output)

Private Attributes

float _density
bool _random
unsigned _randomSeed
Random _prng

Detailed Description

Feature filter that will take source feature and scatter points within that feature. It will either scatter points randomly (the default), or at fixed intervals, based on the density.

Definition at line 37 of file ScatterFilter.


Constructor & Destructor Documentation

ScatterFilter::ScatterFilter ( )

Definition at line 34 of file ScatterFilter.cpp.

                             :
_density   ( 10.0f ),
_random    ( true ),
_randomSeed( 1 )
{
    //NOP
}

Member Function Documentation

float osgEarth::Features::ScatterFilter::getDensity ( ) const [inline]

Definition at line 48 of file ScatterFilter.

{ return _density; }
bool osgEarth::Features::ScatterFilter::getRandom ( ) const [inline]

Definition at line 52 of file ScatterFilter.

{ return _random; }
unsigned osgEarth::Features::ScatterFilter::getRandomSeed ( ) const [inline]

Definition at line 56 of file ScatterFilter.

{ return _randomSeed; }
static bool osgEarth::Features::ScatterFilter::isSupported ( ) [inline, static]

Definition at line 41 of file ScatterFilter.

{ return true; }

Here is the caller graph for this function:

void ScatterFilter::lineScatter ( const Geometry input,
const SpatialReference inputSRS,
const FilterContext context,
PointSet output 
) [protected]

Definition at line 124 of file ScatterFilter.cpp.

{
    // calculate the number of instances per linear km.
    float instPerKm = sqrt( osg::clampAbove( 0.1f, _density ) );

    bool isGeo = inputSRS->isGeographic();

    ConstGeometryIterator iter( input );
    while( iter.hasMore() )
    {
        const Geometry* part = iter.next();

        // see whether it's a ring, because rings have to connect the last two points.
        bool isRing = part->getType() == Geometry::TYPE_RING;
        
        for( unsigned i=0; i<part->size(); ++i )
        {
            // done if we're not traversing a ring.
            if ( !isRing && i+1 == part->size() )
                break;

            // extract the segment:
            const osg::Vec3d& p0 = (*part)[i];
            const osg::Vec3d& p1 = isRing && i+1 == part->size() ? (*part)[0] : (*part)[i+1];

            // figure out the segment length in meters (assumed geodetic coords)
            double seglen_m;
            double seglen_native = (p1-p0).length();
            
            if ( isGeo )
            {
                seglen_m = GeoMath::distance(
                    osg::DegreesToRadians( p0.y() ), osg::DegreesToRadians( p0.x() ),
                    osg::DegreesToRadians( p1.y() ), osg::DegreesToRadians( p1.x() ) );
            }
            else // projected
            {
                seglen_m = seglen_native;
            }

            unsigned numInstances = (seglen_m*0.001) * instPerKm;
            if ( numInstances > 0 )
            {            
                // a unit vector for scattering points along the segment
                osg::Vec3d unit = p1-p0;
                unit.normalize();

                for( unsigned n=0; n<numInstances; ++n )
                {
                    double offset = _prng.next() * seglen_native;
                    output->push_back( p0 + unit*offset );
                }
            }
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void ScatterFilter::polyScatter ( const Geometry input,
const SpatialReference inputSRS,
const FilterContext context,
PointSet output 
) [protected]

Definition at line 43 of file ScatterFilter.cpp.

{
    Bounds bounds;
    double areaSqKm = 0.0;

    ConstGeometryIterator iter( input, false );
    while( iter.hasMore() )
    {
        const Polygon* polygon = dynamic_cast<const Polygon*>( iter.next() );
        if ( !polygon )
            continue;

        if ( /*context.isGeocentric() ||*/ context.profile()->getSRS()->isGeographic() )
        {
            bounds = polygon->getBounds();

            double avglat = bounds.yMin() + 0.5*bounds.height();
            double h = bounds.height() * 111.32;
            double w = bounds.width() * 111.32 * sin( 1.57079633 + osg::DegreesToRadians(avglat) );

            areaSqKm = w * h;
        }

        else if ( context.profile()->getSRS()->isProjected() )
        {
            bounds = polygon->getBounds();
            areaSqKm = (0.001*bounds.width()) * (0.001*bounds.height());
        }

        double zMin = 0.0;
        unsigned numInstancesInBoundingRect = areaSqKm * (double)osg::clampAbove( 0.1f, _density );
        if ( numInstancesInBoundingRect == 0 )
            continue;

        if ( _random )
        {
            // Random scattering. Note, we try to place as many instances as would
            // fit in the bounding rectangle; The real placed number will be less since
            // we only place models inside the actual polygon. But the density will 
            // be correct.
            for( unsigned j=0; j<numInstancesInBoundingRect; ++j )
            {
                double x = bounds.xMin() + _prng.next() * bounds.width();
                double y = bounds.yMin() + _prng.next() * bounds.height();

                bool include = true;

                if ( include && polygon->contains2D( x, y ) )
                    output->push_back( osg::Vec3d(x, y, zMin) );
            }
        }

        else
        {
            // regular interval scattering:
            double numInst1D = sqrt((double)numInstancesInBoundingRect);
            double ar = bounds.width() / bounds.height();
            unsigned cols = (unsigned)( numInst1D * ar );
            unsigned rows = (unsigned)( numInst1D / ar );
            double colInterval = bounds.width() / (double)(cols-1);
            double rowInterval = bounds.height() / (double)(rows-1);
            double interval = 0.5*(colInterval+rowInterval);

            for( double cy=bounds.yMin(); cy<=bounds.yMax(); cy += interval )
            {
                for( double cx = bounds.xMin(); cx <= bounds.xMax(); cx += interval )
                {
                    bool include = true;

                    if ( include && polygon->contains2D( cx, cy ) )
                        output->push_back( osg::Vec3d(cx, cy, zMin) );
                }
            }
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

FilterContext ScatterFilter::push ( FeatureList input,
FilterContext context 
) [virtual]

Processes a new feature list

Implements osgEarth::Features::FeatureFilter.

Definition at line 185 of file ScatterFilter.cpp.

{
    if ( !isSupported() ) {
        OE_WARN << LC << "support for this filter is not enabled" << std::endl;
        return context;
    }

    // seed the random number generator so the randomness is the same each time
    _prng = Random( _randomSeed, Random::METHOD_FAST );

    for( FeatureList::iterator i = features.begin(); i != features.end(); ++i )
    {
        Feature* f = i->get();
        
        Geometry* geom = f->getGeometry();
        if ( !geom )
            continue;

        const SpatialReference* geomSRS = context.profile()->getSRS();

        PointSet* points = new PointSet();

        if ( geom->getComponentType() == Geometry::TYPE_POLYGON )
        {
            polyScatter( geom, geomSRS, context, points );
        }
        else if (
            geom->getComponentType() == Geometry::TYPE_LINESTRING ||
            geom->getComponentType() == Geometry::TYPE_RING )            
        {
            lineScatter( geom, geomSRS, context, points );
        }
        else {
            OE_WARN << LC << "Sorry, don't know how to scatter a PointSet yet" << std::endl;
        }

        // replace the source geometry with the scattered points.
        f->setGeometry( points );
    }

    return context;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void osgEarth::Features::ScatterFilter::setDensity ( float  value) [inline]

Approximate instances per sqkm.

Definition at line 47 of file ScatterFilter.

{ _density = value; }

Here is the caller graph for this function:

void osgEarth::Features::ScatterFilter::setRandom ( bool  value) [inline]

Whether to randomly scatter (as opposed to a fixed interval scatter)

Definition at line 51 of file ScatterFilter.

{ _random = value; }

Here is the caller graph for this function:

void osgEarth::Features::ScatterFilter::setRandomSeed ( unsigned  value) [inline]

Seed value for the random number generator

Definition at line 55 of file ScatterFilter.

{ _randomSeed = value; }

Here is the caller graph for this function:


Member Data Documentation

Definition at line 76 of file ScatterFilter.

Definition at line 79 of file ScatterFilter.

Definition at line 77 of file ScatterFilter.

Definition at line 78 of file ScatterFilter.


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