查看: 8817|回复: 2

API加载earth文件的解析

[复制链接]
  • TA的每日心情
    开心
    2020-3-20 17:50
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2020-3-11 15:34:36 | 显示全部楼层 |阅读模式
    转文章API加载earth文件的解析  。最后一个问题下午解决。
    通过\src\osgEarthDrivers\earth\ReaderWriterOsgEarth.cpp文件
    ReaderWriterEarth类,用来解析“earth”文件
    在文件225行的readNode函数virtual ReadResult readNode(std::istream& in, const osgDB::Options* readOptions) const
            {
                // pull the URI context from the options structure (since we're reading
                // from an "anonymous" stream here)
                URIContext uriContext( readOptions );

                osg::ref_ptr<XmlDocument> doc = XmlDocument::load( in, uriContext );
                if ( !doc.valid() )
                    return ReadResult::ERROR_IN_READING_FILE;

                Config docConf = doc->getConfig();

                // support both "map" and "earth" tag names at the top level
                Config conf;
                if ( docConf.hasChild( "map" ) )
                    conf = docConf.child( "map" );
                else if ( docConf.hasChild( "earth" ) )
                    conf = docConf.child( "earth" );

                osg::ref_ptr<osg::Node> node;

                if ( !conf.empty() )
                {
                    // see if we were given a reference URI to use:
                    std::string refURI = uriContext.referrer();

                    if ( conf.value("version") == "1" )
                    {
                        OE_INFO << LC << "Detected a version 1.x earth file" << std::endl;
                        EarthFileSerializer1 ser;
                        node = ser.deserialize( conf, refURI );
                    }

                    else
                    {
                        if ( conf.value("version") != "2" )
                            OE_DEBUG << LC << "No valid earth file version; assuming version='2'" << std::endl;

                        // attempt to parse a "default options" JSON string:
                        std::string defaultConfStr;
                        if ( readOptions )
                        {
                            defaultConfStr = readOptions->getPluginStringData("osgEarth.defaultOptions");
                            if ( !defaultConfStr.empty() )
                            {
                                Config optionsConf("options");
                                if (optionsConf.fromJSON(defaultConfStr))
                                {
                                    //OE_NOTICE << "\n\nOriginal = \n" << conf.toJSON(true) << "\n";
                                    Config* original = conf.mutable_child("options");
                                    if ( original )
                                    {
                                        recursiveUniqueKeyMerge(optionsConf, *original);
                                    }
                                    if ( !optionsConf.empty() )
                                    {
                                        conf.set("options", optionsConf);
                                    }
                                    //OE_NOTICE << "\n\nMerged = \n" << conf.toJSON(true) << "\n";
                                }
                            }
                        }

                        EarthFileSerializer2 ser;
                        node = ser.deserialize( conf, refURI );
                    }
                }

                MapNode* mapNode = MapNode::get(node.get());
                if (mapNode)
                {
                    // If the user passed in a cache object, apply it to the map now
                    CacheSettings* cacheSettings = CacheSettings::get(readOptions);
                    if (cacheSettings && cacheSettings->getCache())
                    {
                        mapNode->getMap()->setCache( cacheSettings->getCache() );
                        OE_INFO << LC << "Applied user-supplied cache to the Map\n";
                    }
                }

                return ReadResult(node.get());
            }
    };看到65行的读取调用
    进入\src\osgEarthDrivers\earth\EarthFileSerializer2.cpp文件
    EarthFileSerializer2类的deserialize函数
    void addImageLayer(const Config& conf, Map* map)
        {
            ImageLayerOptions options( conf );
            options.name() = conf.value("name");
            ImageLayer* layer = new ImageLayer(options);
            map->addLayer(layer);
            if (layer->getStatus().isError())
                OE_WARN << LC << "Layer \"" << layer->getName() << "\" : " << layer->getStatus().toString() << std::endl;
        }

        void addElevationLayer(const Config& conf, Map* map)
        {
            ElevationLayerOptions options( conf );
            options.name() = conf.value( "name" );
            ElevationLayer* layer = new ElevationLayer(options);
            map->addLayer(layer);
            if (layer->getStatus().isError())
                OE_WARN << LC << "Layer \"" << layer->getName() << "\" : " << layer->getStatus().toString() << std::endl;
        }

        void addModelLayer(const Config& conf, Map* map)
        {
            ModelLayerOptions options( conf );
            options.name() = conf.value( "name" );
            options.driver() = ModelSourceOptions( conf );
            ModelLayer* layer = new ModelLayer(options);
            map->addLayer(layer);
            if (layer->getStatus().isError())
                OE_WARN << LC << "Layer \"" << layer->getName() << "\" : " << layer->getStatus().toString() << std::endl;
        }

        void addMaskLayer(const Config& conf, Map* map)
        {
            MaskLayerOptions options(conf);
            options.name() = conf.value( "name" );
            options.driver() = MaskSourceOptions(options);
            MaskLayer* layer = new MaskLayer(options);
            map->addLayer(layer);
            if (layer->getStatus().isError())
                OE_WARN << LC << "Layer \"" << layer->getName() << "\" : " << layer->getStatus().toString() << std::endl;
        }

        // support for "special" extension names (convenience and backwards compat)
        Extension* createSpecialExtension(const Config& conf)
        {
            // special support for the default sky extension:
            if (conf.key() == "sky" && !conf.hasValue("driver"))
                return Extension::create("sky_simple", conf);

            if (conf.key() == "ocean" && !conf.hasValue("driver"))
                return Extension::create("ocean_simple", conf);

            return 0L;
        }

        bool addLayer(const Config& conf, Map* map)
        {
            std::string name = conf.key();
            Layer* layer = Layer::create(name, conf);
            if (layer)
            {
                map->addLayer(layer);
                if (layer->getStatus().isError())
                    OE_WARN << LC << "Layer \"" << layer->getName() << "\" : " << layer->getStatus().toString() << std::endl;
            }
            return layer != 0L;
        }

    osg::Node*
    EarthFileSerializer2::deserialize( const Config& conf, const std::string& referrer ) const
    {
        // First, pre-load any extension DLLs.
        preloadExtensionLibs(conf);
        preloadExtensionLibs(conf.child("extensions"));
        preloadExtensionLibs(conf.child("external"));

        MapOptions mapOptions( conf.child( "options" ) );

        // legacy: check for name/type in top-level attrs:
        if ( conf.hasValue( "name" ) || conf.hasValue( "type" ) )
        {
            Config legacy;
            if ( conf.hasValue("name") ) legacy.add( "name", conf.value("name") );
            if ( conf.hasValue("type") ) legacy.add( "type", conf.value("type") );
            mapOptions.mergeConfig( legacy );
        }

        Map* map = new Map( mapOptions );

        // Start a batch update of the map:
        map->beginUpdate();

        // Read all the elevation layers in FIRST so other layers can access them for things like clamping.
        for(ConfigSet::const_iterator i = conf.children().begin(); i != conf.children().end(); ++i)
        {
            if ( i->key() == "elevation" || i->key() == "heightfield" )
            {
                addElevationLayer( *i, map );
            }
        }

        Config externalConfig;
        std::vector<osg::ref_ptr<Extension> > extensions;

        // Read the layers in LAST (otherwise they will not benefit from the cache/profile configuration)
        for(ConfigSet::const_iterator i = conf.children().begin(); i != conf.children().end(); ++i)
        {
            if (i->key() == "options" || i->key() == "name" || i->key() == "type" || i->key() == "version")
            {
                // nop - handled earlier
            }

            else if ( i->key() == "image" )
            {
                addImageLayer( *i, map );
            }

            else if ( i->key() == "model" )
            {
                addModelLayer( *i, map );
            }

            else if ( i->key() == "mask" )
            {
                addMaskLayer( *i, map );
            }

            else if ( i->key() == "external" || i->key() == "extensions" )
            {
                externalConfig = *i;
                
                for(ConfigSet::const_iterator e = i->children().begin(); e != i->children().end(); ++e)
                {
                    Extension* extension = loadExtension(*e);
                    if (extension)
                        extensions.push_back(extension);
                    //addExtension( *e, mapNode.get() );
                }
            }

            else if ( !isReservedWord(i->key()) ) // plugins/extensions.
            {
                bool addedLayer = addLayer(*i, map); //mapNode.get());

                if ( !addedLayer )
                {
                    Extension* extension = loadExtension(*i);
                    if (extension)
                        extensions.push_back(extension);
                    //OE_INFO << LC << "Tried to load \"" << i->key() << "\" as a layer; now trying extension\n";
                    //addExtension( *i, mapNode.get() );
                }
            }
        }

        // Complete the batch update of the map
        map->endUpdate();

        // Yes, MapOptions and MapNodeOptions share the same Config node. Weird but true.
        MapNodeOptions mapNodeOptions( conf.child("options") );

        // Create a map node.
        osg::ref_ptr<MapNode> mapNode = new MapNode( map, mapNodeOptions );

        // Apply the external conf if there is one.
        if (!externalConfig.empty())
        {
            mapNode->externalConfig() = externalConfig;
        }

        // Install the extensions
        for (unsigned i = 0; i < extensions.size(); ++i)
        {
            mapNode->addExtension(extensions.at(i).get());
        }

        // return the topmost parent of the mapnode. It's possible that
        // an extension added parents!
        osg::Node* top = mapNode.release();

        while( top->getNumParents() > 0 )
            top = top->getParent(0);

        return top;
    }
    从上面可以看到
    1 earth插件 map 统筹OE中所有"层"的概念,支持多层影像,高程,模型,镂空层(mask)等
    2各个层相应配置的属性由指定的Option类从Config中获取,如果对应Config中有Option类指定元素相应值的配置Option将其写入
    为了统筹OE各个层的属性配置,OE提供了ConfigOptions类,ConfigOptions类就是对某个Config类的封装,提供了到Config层次上的调用,例如Config赋值,拼接等

    为不同层的属性配置提供了存储载体,结合上文map包含的图层有以下关系 20131231222509031.jpg
    通过这些类,可以很方便的将特定的XML节点下属性配置生成Config归类到某一个图层中,以下列出部分图层的属性(仅供参考)

    MapOptions:XML<<options>>节点下配置的信息,主要是配置地形渲染时的属性;包括如下
    <elevation_interploation> 插值,nearset 最近点插值  average 最近点平均值 bilinear 线性插值,  triangulate 三角面片插值  
    <elevation_tile_size> 瓦片大小  
    <elevation_texture_size> 纹理大小  
    <overlay_wapring> 纹理装载  
    <overlay_blending>混合  
    <overlay_minmapping>  纹理映射  
    <overlay_texture_size>  
    <overlay_attach_stencil>模板  


    ImageLayerOptions: XML<<image>>节点下配置的信息,很明显,影像属性配置,部分属性值




    <nodata_image> 无数据显示的url  
    <opacity>    透明度  
    <min_range> 最小可视范围  
    <max_range> 最大可视范围  
    <min_level>  最小显示细节层级  
    <max_level>  最大显示细节层级  
    <min_resolution> 数据的最小分辨率,单位的像素  
    <max_resolution>数据的最大分辨率,单位的像素  
    <enable> 是否包含进map层  
    <visible> 可视  
    ElevationLayerOptions: XML<<elevation>>or<<heightfield>>节点下配置的信息,高程层

    <min_level>  最小显示细节层级  
    <max_level>  最大显示细节层级  
    <min_resolution> 数据的最小分辨率,单位的像素  
    <max_resolution>数据的最大分辨率,单位的像素  
    <enable> 是否包含进map层  
    ModelLayerOptions: XML<<Model>>节点下配置的信息 模型层装载 矢量数据,模型,几何体等
    <name>  
    <driver>  
    <enable><span style="font-family:Arial, Helvetica, sans-serif;">是否包含进map层</span>  
    <visible>是否可见  
    <overLay>  
    MaskLayerOptions: XML<<mask>>节点配置下的信息,镂空层

    一个比较特殊的节点 ext(Config); 暂且叫他功能层,XML <<external>>,它由mapNode直接读取配置信息,实现一些经常用到的功能点,例如 视点定位 <<<viewpoint>> 星空时刻设置<<sky>>

    最后的masklayer
    <mask driver="feature" name="mask">
            <features driver="ogr">
                <geometry>
                    POLYGON(( -111.0466 42.0015 0, -111.0467 40.9979 0, -109.0501 41.0007 0, -109.0452 36.9991 0, -114.0506 37.0004 0, -114.0417 41.9937 0))
                </geometry>
            </features>
            <profile>global-geodetic</profile>
        </mask>
  • TA的每日心情
    开心
    2020-3-20 17:50
  • 签到天数: 1 天

    [LV.1]初来乍到

     楼主| 发表于 2020-3-11 15:37:09 | 显示全部楼层
    api开发的方式   char *driver = Tcl_GetString(objv[5]);
    2001                char *format = Tcl_GetString(objv[6]);
    2002                if (format && strlen(format) > 0 &&
    2003                    strcmp(format, "json") != 0 && strcmp(format, "gml") != 0) {
    2004                    Tcl_AppendResult(interp, "unknown format \"", format,
    2005                                     "\": should be 'json' or 'gml'", (char*)NULL);
    2006                    return TCL_ERROR;
    2007                }
    2008                char *typeName = Tcl_GetString(objv[7]);
    2009                osgEarth:rivers::FeatureMaskOptions maskOpts;
    2010                std::string url;
    2011                if (objc > 8) {
    2012                    if (driver[0] == 'w' && strcmp(driver, "wkt") == 0) {
    2013                        url = Tcl_GetString(objv[8]);
    2014                        if (url.empty()) {
    2015                            Tcl_AppendResult(interp, "Empty WKT length",
    2016                                             (char*)NULL);
    2017                            return TCL_ERROR;
    2018                        }
    2019                    } else {
    2020                        char *urlIn = Tcl_GetString(objv[8]);
    2021                        url = g_renderer->getCanonicalPath(std::string(urlIn));
    2022                        if (url.empty()) {
    2023                            Tcl_AppendResult(interp, "file not found: \"",
    2024                                             urlIn, "\"", (char*)NULL);
    2025                            return TCL_ERROR;
    2026                        }
    2027                    }
    2028                }
    2029                if (driver[0] == 'd' && strcmp(driver, "db") == 0) {
    2030                    osgEarth::Drivers::OGRFeatureOptions opts;
    2031                    opts.name() = name;
    2032                    opts.connection() = url;
    2033                    opts.layer() = typeName;
    2034                    maskOpts.featureOptions() = opts;
    2035                } else if (driver[0] == 'o' && strcmp(driver, "ogr") == 0) {
    2036                    osgEarth::Drivers::OGRFeatureOptions opts;
    2037                    opts.name() = name;
    2038                    opts.url() = url;
    2039                    maskOpts.featureOptions() = opts;
    2040                } else if (driver[0] == 't' && strcmp(driver, "tfs") == 0) {
    2041                    osgEarth::Drivers::TFSFeatureOptions opts;
    2042                    opts.name() = name;
    2043                    opts.url() = url;
    2044                    opts.format() = format;
    2045                    maskOpts.featureOptions() = opts;
    2046                } else if (driver[0] == 'w' && strcmp(driver, "wfs") == 0) {
    2047                    osgEarth::Drivers::WFSFeatureOptions opts;
    2048                    opts.name() = name;
    2049                    opts.url() = url;
    2050                    opts.outputFormat() = format;
    2051                    opts.typeName() = typeName;
    2052                    maskOpts.featureOptions() = opts;
    2053                } else if (driver[0] == 'w' && strcmp(driver, "wkt") == 0) {
    2054                    // Inline geometry, url is length of following data
    2055                    char *ptr;
    2056                    long len = strtol(url.c_str(), &ptr, 10);
    2057                    if (len <= 0 || *ptr != '\0') {
    2058                        Tcl_AppendResult(interp, "Failed to parse WKT length: \"",
    2059                                         url.c_str(), "\"", (char*)NULL);
    2060                        return TCL_ERROR;
    2061                    }
    2062                    char *wkt = (char *)malloc((size_t)len);
    2063                    if (!SocketRead(wkt, len)) {
    2064                        free(wkt);
    2065                        Tcl_AppendResult(interp, "Failed to read WKT string",
    2066                                         (char*)NULL);
    2067                        return TCL_ERROR;
    2068                    }
    2069                    osgEarth::Drivers::OGRFeatureOptions opts;
    2070                    opts.name() = name;
    2071                    TRACE("Geometry: \"%s\"", wkt);
    2072                    osgEarth::Config conf("geometry", std::string(wkt));
    2073                    free(wkt);
    2074                    opts.geometryConfig() = conf;
    2075                    maskOpts.featureOptions() = opts;
    2076                } else if (driver[0] == 'w' && strcmp(driver, "wkt_file") == 0) {
    2077                    osgEarth::Drivers::OGRFeatureOptions opts;
    2078                    opts.name() = name;
    2079                    opts.geometryUrl() = url;
    2080                    maskOpts.featureOptions() = opts;
    2081                } else {
    2082                    Tcl_AppendResult(interp, "unknown mask driver \"", driver,
    2083                                     "\": should be 'db', 'ogr', 'tfs', 'wfs', 'wkt', or 'wkt_file'", (char*)NULL);
    2084                    return TCL_ERROR;
    2085                }
    2086                int minLOD = 0;
    2087                if (objc > 9) {
    2088                    if (Tcl_GetIntFromObj(interp, objv[9], &minLOD) != TCL_OK) {
    2089                        return TCL_ERROR;
    2090                    }
    2091                }
    2092                g_renderer->addTerrainMaskLayer(name, maskOpts, (unsigned)minLOD);
  • TA的每日心情
    开心
    2020-3-20 17:50
  • 签到天数: 1 天

    [LV.1]初来乍到

     楼主| 发表于 2020-3-11 15:57:00 | 显示全部楼层
    本帖最后由 liyihongcug 于 2020-3-11 16:18 编辑

    例如
    <options type="geocentric">
        <cache path="d:/test/cache_dir" type="filesystem" />
        <terrain first_lod="0" tile_size="17" />
      </options>
    <options>
            <lighting>false</lighting>
            <overlay_blending>false</overlay_blending>
            <terrain min_lod="8"/>
        </options>

    MapOptions( const ConfigOptions& options =ConfigOptions() )
                : ConfigOptions          ( options ),
                  _cachePolicy           ( ),
                  _cstype                ( CSTYPE_GEOCENTRIC ),
                  _referenceURI          ( "" ),
                  _elevationInterpolation( INTERP_BILINEAR )
    MapOptions MapOptions.cpp
          optional<std::string>            _name;
            optional<rofileOptions>         _profileOptions;
            optional<CacheOptions>           _cacheOptions;
            optional<CachePolicy>            _cachePolicy;
            optional<CoordinateSystemType>   _cstype;
            optional<std::string>            _referenceURI;
            optional<ElevationInterpolation> _elevationInterpolation;

    terrain的源文件在TerrainOptions.cpp
    MapOptions:XML<<options>>节点下配置的信息,主要是配置地形渲染时的属性;包括如下
    <elevation_interploation> 插值,nearset 最近点插值  average 最近点平均值 bilinear 线性插值,  triangulate 三角面片插值  
    <elevation_tile_size> 瓦片大小  
    <elevation_texture_size> 纹理大小  
    <overlay_wapring> 纹理装载  
    <overlay_blending>混合  
    <overlay_minmapping>  纹理映射  
    <overlay_texture_size>  
    <overlay_attach_stencil>模板     2.8里没有这些参数,2.10才有


    TerrainOptions::getConfig() const
    {
        Config conf = DriverConfigOptions::getConfig();
        conf.key() = "terrain";
       
        conf.updateIfSet( "tile_size", _tileSize );
        conf.updateIfSet( "vertical_scale", _verticalScale );
        conf.updateIfSet( "vertical_offset", _verticalOffset );
        conf.updateIfSet( "min_tile_range_factor", _minTileRangeFactor );
        conf.updateIfSet( "range_factor", _minTileRangeFactor );  
        conf.updateIfSet( "max_lod", _maxLOD );
        conf.updateIfSet( "min_lod", _minLOD );
        conf.updateIfSet( "first_lod", _firstLOD );
        conf.updateIfSet( "lighting", _enableLighting );
        conf.updateIfSet( "attenuation_distance", _attenuationDistance );
        conf.updateIfSet( "lod_transition_time", _lodTransitionTimeSeconds );
        conf.updateIfSet( "mipmapping", _enableMipmapping );
        conf.updateIfSet( "cluster_culling", _clusterCulling );
        conf.updateIfSet( "blending", _enableBlending );
        conf.updateIfSet( "mercator_fast_path", _mercatorFastPath );
        conf.updateIfSet( "min_normal_map_lod", _minNormalMapLOD );
        conf.updateIfSet( "gpu_tessellation", _gpuTessellation );
        conf.updateIfSet( "debug", _debug );
        conf.updateIfSet( "bin_number", _binNumber );
        conf.updateIfSet( "min_expiry_time", _minExpiryTime);
        conf.updateIfSet( "min_expiry_frames", _minExpiryFrames);

        //Save the filter settings
            conf.updateIfSet("mag_filter","LINEAR",                _magFilter,osg::Texture:INEAR);
        conf.updateIfSet("mag_filter","LINEAR_MIPMAP_LINEAR",  _magFilter,osg::Texture::LINEAR_MIPMAP_LINEAR);
        conf.updateIfSet("mag_filter","LINEAR_MIPMAP_NEAREST", _magFilter,osg::Texture::LINEAR_MIPMAP_NEAREST);
        conf.updateIfSet("mag_filter","NEAREST",               _magFilter,osg::Texture::NEAREST);
        conf.updateIfSet("mag_filter","NEAREST_MIPMAP_LINEAR", _magFilter,osg::Texture::NEAREST_MIPMAP_LINEAR);
        conf.updateIfSet("mag_filter","NEAREST_MIPMAP_NEAREST",_magFilter,osg::Texture::NEAREST_MIPMAP_NEAREST);
        conf.updateIfSet("min_filter","LINEAR",                _minFilter,osg::Texture::LINEAR);
        conf.updateIfSet("min_filter","LINEAR_MIPMAP_LINEAR",  _minFilter,osg::Texture::LINEAR_MIPMAP_LINEAR);
        conf.updateIfSet("min_filter","LINEAR_MIPMAP_NEAREST", _minFilter,osg::Texture::LINEAR_MIPMAP_NEAREST);
        conf.updateIfSet("min_filter","NEAREST",               _minFilter,osg::Texture::NEAREST);
        conf.updateIfSet("min_filter","NEAREST_MIPMAP_LINEAR", _minFilter,osg::Texture::NEAREST_MIPMAP_LINEAR);
        conf.updateIfSet("min_filter","NEAREST_MIPMAP_NEAREST",_minFilter,osg::Texture::NEAREST_MIPMAP_NEAREST);

        return conf;
    }
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    OSG中国官方论坛-有您OSG在中国才更好

    网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

    联系我们

    • 工作时间:09:00--18:00
    • 反馈邮箱:1315785073@qq.com
    快速回复 返回顶部 返回列表