osgEarth的Rex引擎原理分析(一二六)rex瓦片组织方式

本文深入探讨osgEarth的Rex引擎中瓦片的组织方式,重点解析Profile在地图文件中的设置及其对瓦片分片方案的影响。内容涉及earth文件的Map和Image下的Profile配置,以及它们之间的关联。文章还列举了一系列待分析的问题,涵盖osgEarth的各个组件和机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目标:(一二五)中问题212

通过如下确定瓦片的组织方式 ,核心是profile

osgEarth/Map.cpp
void
Map::calculateProfile()
{
    // collect the terrain layers; we will need them later
    TerrainLayerVector layers;
    getLayers(layers);

    // Figure out the map profile:
    if ( !_profile.valid() )
    {
        osg::ref_ptr<const Profile> profile;

        // Do the map options contain a profile? If so, try to use it:
        if ( _mapOptions.profile().isSet() )
        {
            profile = Profile::create( _mapOptions.profile().value() );
        }

        // Do the map options contain an override coordinate system type?
        // If so, attempt to apply that next:
        if (_mapOptions.coordSysType().isSetTo(MapOptions::CSTYPE_GEOCENTRIC))
        {
            if (profile.valid() && profile->getSRS()->isProjected())
            {
                OE_WARN << LC << "Geocentric map type conflicts with the projected SRS profile; ignoring your profile\n";
                profile = Registry::instance()->getGlobalGeodeticProfile();
            }
        }

        // Do the map options ask for a projected map?
        else if (_mapOptions.coordSysType().isSetTo(MapOptions::CSTYPE_PROJECTED))
        {
            // Is there a conflict in the MapOptions?
            if (profile.valid() && profile->getSRS()->isGeographic())
            {
                OE_WARN << LC << "Projected map type conflicts with the geographic SRS profile; converting to Equirectangular projection\n";
                unsigned u, v;
                profile->getNumTiles(0, u, v);
                const osgEarth::SpatialReference* eqc = profile->getSRS()->createEquirectangularSRS();
                osgEarth::GeoExtent e = profile->getExtent().transform( eqc );
                profile = osgEarth::Profile::create( eqc, e.xMin(), e.yMin(), e.xMax(), e.yMax(), u, v);
            }

            // Is there no profile set? Try to derive it from the Map layers:
            if (!profile.valid())
            {
                for (TerrainLayerVector::iterator i = layers.begin(); !profile.valid() && i != layers.end(); ++i)
                {
                    profile = i->get()->getProfile();
                }
            }

            if (!profile.valid())
            {
                OE_WARN << LC << "No profile information available; defaulting to Spherical Mercator projection\n";
                profile = Registry::instance()->getSphericalMercatorProfile();
            }
        }

        // Finally, if there is still no profile, default to global geodetic.
        if (!profile.valid())
        {            
            profile = Registry::instance()->getGlobalGeodeticProfile();
        }


        // Set the map's profile!
        _profile = profile.release();        

        // create a "proxy" profile to use when querying elevation layers with a vertical datum
        if ( _profile->getSRS()->getVerticalDatum() != 0L )
        {
            ProfileOptions po = _profile->toProfileOptions();
            po.vsrsString().unset();
            _profileNoVDatum = Profile::create(po);
        }
        else
        {
            _profileNoVDatum = _profile;
        }

        // finally, fire an event if the profile has been set.
        OE_INFO << LC << "Map profile is: " << _profile->toString() << std::endl;

        for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
        {
            i->get()->onMapInfoEstablished( MapInfo(this) );
        }
    }

    // Tell all the layers about the profile
    for (TerrainLayerVector::iterator i = layers.begin(); i != layers.end(); ++i)
    {
        if (i->get()->getEnabled())
        {
            i->get()->setTargetProfileHint(_profile.get());
        }
    }
}

profile在earth文件中的设置如下


<options>
			<profile>
          <srs>epsg:4326</srs>
          <xmin>-180.0</xmin>
          <ymin>-90.0</ymin>
          <xmax>180.0</xmax>
          <ymax>90.0</ymax>
        	<num_tiles_wide_at_lod_0>1</num_tiles_wide_at_lod_0>
			  	<num_tiles_high_at_lod_0>1</num_tiles_high_at_lod_0>  
      </profile>    
    </options>

 可设置的属性如下

class OSGEARTH_EXPORT ProfileOptions : public ConfigOptions
    {
        optional<std::string> _namedProfile;
        optional<std::string> _srsInitString;
        optional<std::string> _vsrsInitString;
        optional<Bounds>      _bounds;
        optional<int>         _numTilesWideAtLod0;
        optional<int>         _numTilesHighAtLod0;
    };
osgEarth/Profile.cpp
void
ProfileOptions::fromConfig( const Config& conf )
{
    if ( !conf.value().empty() )
        _namedProfile = conf.value();

    conf.getIfSet( "srs", _srsInitString );

    conf.getIfSet( "vdatum", _vsrsInitString );
    conf.getIfSet( "vsrs", _vsrsInitString ); // back compat

    if ( conf.hasValue( "xmin" ) && conf.hasValue( "ymin" ) && conf.hasValue( "xmax" ) && conf.hasValue( "ymax" ) )
    {
        _bounds = Bounds(
            conf.value<double>( "xmin", 0 ),
            conf.value<double>( "ymin", 0 ),
            conf.value<double>( "xmax", 0 ),
            conf.value<double>( "ymax", 0 ) );
    }

    conf.getIfSet( "num_tiles_wide_at_lod_0", _numTilesWideAtLod0 );
    conf.getIfSet( "num_tiles_high_at_lod_0", _numTilesHighAtLod0 );
}

以上为Map下的profile,在image下也有profile,它们是有关系的,主要体现在intersectingKeys上,一般将这两个profile设置成一样的。

<image name="mapbox_satellite" driver="xyz">
        <url>http://online2.map.bdimg.com/tile/?qt=tile&amp;x={x}&amp;y={y}&amp;z={z}&amp;styles=pl&amp;udt=20171031&amp;scaler=1&amp;p=1</url>
        <profile>
          <srs>epsg:4326</srs>
          <xmin>-180.0</xmin>
          <ymin>-90.0</ymin>
          <xmax>180.0</xmax>
          <ymax>90.0</ymax>
        	<num_tiles_wide_at_lod_0>2</num_tiles_wide_at_lod_0>
			  	<num_tiles_high_at_lod_0>2</num_tiles_high_at_lod_0>  
        </profile>             
	  </image>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值