Beispiel #1
0
osg::Node*
Graticule::createGridLevel( unsigned int levelNum ) const
{
    if ( !_map->isGeocentric() )
    {
        OE_WARN << "Graticule: only supports geocentric maps" << std::endl;
        return 0L;
    }

    Graticule::Level level;
    if ( !getLevel( levelNum, level ) )
        return 0L;

    OE_DEBUG << "Graticule: creating grid level " << levelNum << std::endl;

    osg::Group* group = new osg::Group();

    const Profile* mapProfile = _map->getProfile();
    const GeoExtent& pex = mapProfile->getExtent();

    double tw = pex.width() / (double)level._cellsX;
    double th = pex.height() / (double)level._cellsY;

    for( unsigned int x=0; x<level._cellsX; ++x )
    {
        for( unsigned int y=0; y<level._cellsY; ++y )
        {
            GeoExtent tex(
                mapProfile->getSRS(),
                pex.xMin() + tw * (double)x,
                pex.yMin() + th * (double)y,
                pex.xMin() + tw * (double)(x+1),
                pex.yMin() + th * (double)(y+1) );

            double ox = level._lineWidth;
            double oy = level._lineWidth;

            Geometry* geom = createCellGeometry( tex, level._lineWidth, pex, _map->isGeocentric() );

            Feature* feature = new Feature();
            feature->setGeometry( geom );
            FeatureList features;
            features.push_back( feature );

            FilterContext cx;
            cx.profile() = new FeatureProfile( tex );
            cx.isGeocentric() = _map->isGeocentric();

            if ( _map->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.
                ResampleFilter resample;
                resample.maxLength() = tex.width() / 10.0;
                resample.perturbationThreshold() = level._lineWidth/1000.0;
                cx = resample.push( features, cx );
            }

            TransformFilter xform( mapProfile->getSRS() );
            xform.setMakeGeocentric( _map->isGeocentric() );
            cx = xform.push( features, cx );

            Bounds bounds = feature->getGeometry()->getBounds();
            double exDist = bounds.radius()/2.0;

            osg::Node* cellVolume = createVolume(
                feature->getGeometry(),
                -exDist,
                exDist*2,
                cx );

            osg::Node* child = cellVolume;

            if ( cx.hasReferenceFrame() )
            {
                osg::MatrixTransform* xform = new osg::MatrixTransform( cx.inverseReferenceFrame() );
                xform->addChild( child );

                // the transform matrix here does NOT include a rotation, so we need to get the normal
                // for the cull plane callback.
                osg::Vec3d normal = xform->getBound().center();
                xform->setCullCallback( new CullPlaneCallback( normal ) );

                child = xform;
            }

            group->addChild( child );
        }
    }

    // organize it for better culling
    osgUtil::Optimizer opt;
    opt.optimize( group, osgUtil::Optimizer::SPATIALIZE_GROUPS );

    osg::Node* result = group;

    if ( levelNum+1 < getNumLevels() )
    {
        Graticule::Level nextLevel;
        if ( getLevel( levelNum+1, nextLevel ) )
        {
            osg::PagedLOD* plod = new osg::PagedLOD();
            plod->addChild( group, nextLevel._maxRange, level._maxRange );
            std::stringstream buf;
            buf << levelNum+1 << "_" << getID() << "." << GRID_MARKER << "." << GRATICLE_EXTENSION;
            std::string bufStr = buf.str();
            plod->setFileName( 1, bufStr );
            plod->setRange( 1, 0, nextLevel._maxRange );
            result = plod;
        }
    }

    return result;
}