目标:(七十二)中的问题147

高程文件的划分规则和rex瓦片是不一样的,高程文件的0级就是文件本身,不管文件实际范围多大,然后采用二分法逐级增加。rex瓦片的0级对应整个地球表面。

两个范围一般不是一一对应的,秘密尽在

1、首先根据rex瓦片的范围从高程文件中找出相交的高程文件瓦片(该瓦片不同于rex瓦片,是和高程文件对应的瓦片,瓦片尺寸和rex瓦片最为接近)

2、从相交的高程文件瓦片构建出一个中间高程场,以上两步在这里完成

osgEarth/ElevationLayer.cpp
void
ElevationLayer::assembleHeightField(const TileKey& key,osg::ref_ptr<osg::HeightField>& out_hf,osg::ref_ptr<NormalMap>& out_normalMap,ProgressCallback* progress)
{           //osg::HeightField* result = 0L;// Collect the heightfields for each of the intersecting tiles.GeoHeightFieldVector heightFields;//Determine the intersecting keysstd::vector< TileKey > intersectingTiles;getProfile()->getIntersectingTiles( key, intersectingTiles );//获取相交的高程文件瓦片// collect heightfield for each intersecting key. Note, we're hitting the// underlying tile source here, so there's no vetical datum shifts happening yet.// we will do that later.if ( intersectingTiles.size() > 0 ){for (unsigned int i = 0; i < intersectingTiles.size(); ++i){const TileKey& layerKey = intersectingTiles[i];if ( isKeyInLegalRange(layerKey) ){osg::ref_ptr<osg::HeightField> hf;osg::ref_ptr<NormalMap> normalMap;createImplementation(layerKey, hf, normalMap, progress);//osg::HeightField* hf = createHeightFieldImplementation( layerKey, progress );if (hf.valid()){heightFields.push_back( GeoHeightField(hf.get(), normalMap.get(), layerKey.getExtent()) );}}}}// If we actually got a HeightField, resample/reproject it to match the incoming TileKey's extents.if (heightFields.size() > 0){      unsigned int width = 0;unsigned int height = 0;for (GeoHeightFieldVector::iterator itr = heightFields.begin(); itr != heightFields.end(); ++itr){if (itr->getHeightField()->getNumColumns() > width)width = itr->getHeightField()->getNumColumns();if (itr->getHeightField()->getNumRows() > height) height = itr->getHeightField()->getNumRows();                        }//Now sort the heightfields by resolution to make sure we're sampling the highest resolution one first.std::sort( heightFields.begin(), heightFields.end(), GeoHeightField::SortByResolutionFunctor());        out_hf = new osg::HeightField();out_hf->allocate(width, height);out_normalMap = new NormalMap(width, height);//Go ahead and set up the heightfield so we don't have to worry about it laterdouble minx, miny, maxx, maxy;key.getExtent().getBounds(minx, miny, maxx, maxy);double dx = (maxx - minx)/(double)(width-1);double dy = (maxy - miny)/(double)(height-1);//Create the new heightfield by sampling all of them.for (unsigned int c = 0; c < width; ++c){double x = minx + (dx * (double)c);for (unsigned r = 0; r < height; ++r){double y = miny + (dy * (double)r);//For each sample point, try each heightfield.  The first one with a valid elevation wins.float elevation = NO_DATA_VALUE;osg::Vec3 normal(0,0,1);for (GeoHeightFieldVector::iterator itr = heightFields.begin(); itr != heightFields.end(); ++itr){// get the elevation value, at the same time transforming it vertically into the // requesting key's vertical datum.float e = 0.0;osg::Vec3 n;if (itr->getElevationAndNormal(key.getExtent().getSRS(), x, y, INTERP_BILINEAR, key.getExtent().getSRS(), e, n)){elevation = e;normal = n;break;}}out_hf->setHeight( c, r, elevation ); //设置中间高程场,最终的rex瓦片高程来自于此out_normalMap->set( c, r, normal );}}}
}

3、将中间高程场提取出rex瓦片的高程,该步在下面完成


bool
ElevationLayerVector::populateHeightFieldAndNormalMap(osg::HeightField*      hf,NormalMap*             normalMap,const TileKey&         key,const Profile*         haeProfile,ElevationInterpolation interpolation,ProgressCallback*      progress ) const
{// heightfield must already exist.if ( !hf )return false;METRIC_SCOPED("ElevationLayer.populateHeightField");// if the caller provided an "HAE map profile", he wants an HAE elevation grid even if// the map profile has a vertical datum. This is the usual case when building the 3D// terrain, for example. Construct a temporary key that doesn't have the vertical// datum info and use that to query the elevation data.TileKey keyToUse = key;if ( haeProfile ){keyToUse = TileKey(key.getLOD(), key.getTileX(), key.getTileY(), haeProfile );}// Collect the valid layers for this tile.LayerDataVector contenders;LayerDataVector offsets;// Track the number of layers that would return fallback data.unsigned numFallbackLayers = 0;// Check them in reverse order since the highest priority is last.for (int i = size()-1; i>=0; --i)//for(ElevationLayerVector::const_reverse_iterator i = this->rbegin(); i != this->rend(); ++i){ElevationLayer* layer = (*this)[i].get(); //i->get();if ( layer->getEnabled() && layer->getVisible() ){// calculate the resolution-mapped key (adjusted for tile resolution differential).            TileKey mappedKey = keyToUse.mapResolution(hf->getNumColumns(),layer->getTileSize() );bool useLayer = true;TileKey bestKey( mappedKey );// Check whether the non-mapped key is valid according to the user's min/max level settings:if ( !layer->isKeyInLegalRange(key) ){useLayer = false;}// Find the "best available" mapped key from the tile source:else {bestKey = layer->getBestAvailableTileKey(mappedKey);if (bestKey.valid()){// If the bestKey is not the mappedKey, this layer is providing// fallback data (data at a lower resolution than requested)if ( mappedKey != bestKey ){numFallbackLayers++;}}else{useLayer = false;}}if ( useLayer ){if ( layer->isOffset() ){offsets.push_back(LayerData());LayerData& ld = offsets.back();ld.layer = layer;ld.key = bestKey;ld.index = i;}else{contenders.push_back(LayerData());LayerData& ld = contenders.back();ld.layer = layer;ld.key = bestKey;ld.index = i;}}}}// nothing? bail out.if ( contenders.empty() && offsets.empty() ){return false;}// if everything is fallback data, bail out.if ( contenders.size() + offsets.size() == numFallbackLayers ){return false;}// Sample the layers into our target.unsigned numColumns = hf->getNumColumns();unsigned numRows    = hf->getNumRows();    double   xmin       = key.getExtent().xMin();double   ymin       = key.getExtent().yMin();double   dx         = key.getExtent().width() / (double)(numColumns-1);double   dy         = key.getExtent().height() / (double)(numRows-1);#if 0// If the incoming heightfield requests a positive border width, // we need to adjust the extents so that we request data outside the// extent of the tile key:unsigned border = hf->getBorderWidth();if (border > 0u){dx = key.getExtent().width() / (double)(numColumns - (border*2+1));dy = key.getExtent().height() / (double)(numRows - (border*2+1));xmin -= dx * (double)border;ymin -= dy * (double)border;}
#endif// We will load the actual heightfields on demand. We might not need them all.
#if 0GeoHeightFieldVector heightFields(contenders.size());GeoHeightFieldVector offsetFields(offsets.size());std::vector<bool>    heightFallback(contenders.size(), false);std::vector<bool>    heightFailed(contenders.size(), false);std::vector<bool>    offsetFailed(offsets.size(), false);
#elseGeoHeightFieldVector heightFields[9];GeoHeightFieldVector offsetFields[9]; //(offsets.size());std::vector<bool>    heightFallback[9]; //(contenders.size(), false);std::vector<bool>    heightFailed[9]; //(contenders.size(), false);std::vector<bool>    offsetFailed[9]; //(offsets.size(), false);for (int n = 0; n < 9; ++n){heightFields[n].resize(contenders.size());offsetFields[n].resize(offsets.size());heightFallback[n].assign(9, false);heightFailed[n].assign(9, false);offsetFailed[n].assign(9, false);}
#endif// The maximum number of heightfields to keep in this local cacheunsigned int maxHeightFields = 50;unsigned numHeightFieldsInCache = 0;const SpatialReference* keySRS = keyToUse.getProfile()->getSRS();bool realData = false;unsigned int total = numColumns * numRows;// query resolution interval (x, y) of each sample.osg::ref_ptr<osg::ShortArray> deltaLOD = new osg::ShortArray(total);int nodataCount = 0;TileKey scratchKey; // Storage if a new key needs to be constructedfor (unsigned c = 0; c < numColumns; ++c){double x = xmin + (dx * (double)c);for (unsigned r = 0; r < numRows; ++r){double y = ymin + (dy * (double)r);// Collect elevations from each layer as necessary.int resolvedIndex = -1;osg::Vec3 normal_sum(0,0,0);for(int i=0; i<contenders.size() && resolvedIndex<0; ++i){ElevationLayer* layer = contenders[i].layer.get();                TileKey& contenderKey = contenders[i].key;int index = contenders[i].index;// If there is a border, the edge points may not fall within the key extents // and we may need to fetch a neighboring key.int n = 4; // index 4 is the center/default tile#if 0if (border > 0u && !contenderKey.getExtent().contains(x, y)){int dTx = x < contenderKey.getExtent().xMin() ? -1 : x > contenderKey.getExtent().xMax() ? +1 : 0;int dTy = y < contenderKey.getExtent().yMin() ? +1 : y > contenderKey.getExtent().yMax() ? -1 : 0;contenderKey = contenderKey.createNeighborKey(dTx, dTy);n = (dTy+1)*3 + (dTx+1);}
#endifif ( heightFailed[n][i] )continue;TileKey* actualKey = &contenderKey;GeoHeightField& layerHF = heightFields[n][i];if (!layerHF.valid()){// We couldn't get the heightfield from the cache, so try to create it.// We also fallback on parent layers to make sure that we have data at the location even if it's fallback.while (!layerHF.valid() && actualKey->valid() && layer->isKeyInLegalRange(*actualKey)){layerHF = layer->createHeightField(*actualKey, progress);if (!layerHF.valid()){if (actualKey != &scratchKey){scratchKey = *actualKey;actualKey = &scratchKey;}*actualKey = actualKey->createParentKey();}}// Mark this layer as fallback if necessary.if (layerHF.valid()){heightFallback[n][i] = (*actualKey != contenderKey); // actualKey != contenders[i].second;numHeightFieldsInCache++;}else{heightFailed[n][i] = true;continue;}}if (layerHF.valid()){bool isFallback = heightFallback[n][i];// We only have real data if this is not a fallback heightfield.if (!isFallback){realData = true;}float elevation;if (layerHF.getElevation(keySRS, x, y, interpolation, keySRS, elevation)){if ( elevation != NO_DATA_VALUE ){// remember the index so we can only apply offset layers that// sit on TOP of this layer.resolvedIndex = index;hf->setHeight(c, r, elevation);//从中间高程场构建最终的rex高程瓦片if (deltaLOD){(*deltaLOD)[r*numColumns + c] = key.getLOD() - actualKey->getLOD();}}else{++nodataCount;}}                    }// Clear the heightfield cache if we have too many heightfields in the cache.if (numHeightFieldsInCache >= maxHeightFields){//OE_NOTICE << "Clearing cache" << std::endl;for (unsigned int j = 0; j < 9; ++j){for (unsigned int k = 0; k < heightFields[j].size(); k++){heightFields[j][k] = GeoHeightField::INVALID;heightFallback[j][k] = false;}}numHeightFieldsInCache = 0;}}for(int i=offsets.size()-1; i>=0; --i){// Only apply an offset layer if it sits on top of the resolved layer// (or if there was no resolved layer).if (resolvedIndex >= 0 && offsets[i].index < resolvedIndex)continue;TileKey &contenderKey = offsets[i].key;// If there is a border, the edge points may not fall within the key extents // and we may need to fetch a neighboring key.int n = 4; // index 4 is the center/default tile#if 0if (border > 0u && !contenderKey.getExtent().contains(x, y)){int dTx = x < contenderKey.getExtent().xMin() ? -1 : x > contenderKey.getExtent().xMax() ? +1 : 0;int dTy = y < contenderKey.getExtent().yMin() ? +1 : x > contenderKey.getExtent().yMax() ? -1 : 0;contenderKey = contenderKey.createNeighborKey(dTx, dTy);n = (dTy+1)*3 + (dTx+1);}
#endifif ( offsetFailed[n][i] == true )continue;GeoHeightField& layerHF = offsetFields[n][i];if ( !layerHF.valid() ){ElevationLayer* offset = offsets[i].layer.get();layerHF = offset->createHeightField(contenderKey, progress);if ( !layerHF.valid() ){offsetFailed[n][i] = true;continue;}}// If we actually got a layer then we have real datarealData = true;float elevation = 0.0f;if (layerHF.getElevation(keySRS, x, y, interpolation, keySRS, elevation) &&elevation != NO_DATA_VALUE){                    hf->getHeight(c, r) += elevation;// Update the resolution tracker to account for the offset. Sadly this// will wipe out the resolution of the actual data, and might result in // normal faceting. See the comments on "createNormalMap" for more infoif (deltaLOD){(*deltaLOD)[r*numColumns + c] = key.getLOD() - contenderKey.getLOD();}}}}}if (normalMap){createNormalMap(key.getExtent(), hf, deltaLOD.get(), normalMap);}// Return whether or not we actually read any real datareturn realData;
}

gdal判断外部瓦片和文件瓦片是否相交要用到下面的变换函数,如果不能正确变换会判断不相交。

gdal中OCTTransform( xform_handle, count, x, y, 0L )函数的含义是什么

gdal-2.2.2\ogr\ogrct.cpp
/************************************************************************/
/*                            OCTTransform()                            */
/************************************************************************//** Transform an array of points** @param hTransform Transformation object* @param nCount Number of points* @param x Array of nCount x values.* @param y Array of nCount y values.* @param z Array of nCount z values.* @return TRUE or FALSE*/
int CPL_STDCALL OCTTransform( OGRCoordinateTransformationH hTransform,int nCount, double *x, double *y, double *z ){VALIDATE_POINTER1( hTransform, "OCTTransform", FALSE );return ((OGRCoordinateTransformation*) hTransform)->Transform( nCount, x, y, z );
}/************************************************************************/
/*                              OGRProj4CT                              */
/************************************************************************/class OGRProj4CT : public OGRCoordinateTransformation/************************************************************************/
/*                             Transform()                              */
/*                                                                      */
/*      This is a small wrapper for the extended transform version.     */
/************************************************************************/int OGRProj4CT::Transform( int nCount, double *x, double *y, double *z ){int *pabSuccess = static_cast<int *>(CPLMalloc(sizeof(int) * nCount));bool bOverallSuccess =CPL_TO_BOOL(TransformEx( nCount, x, y, z, pabSuccess ));for( int i = 0; i < nCount; i++ ){if( !pabSuccess[i] ){bOverallSuccess = false;break;}}CPLFree( pabSuccess );return bOverallSuccess;
}/************************************************************************/
/*                            TransformEx()                             */
/************************************************************************//** Transform an array of points** @param nCount Number of points* @param x Array of nCount x values.* @param y Array of nCount y values.* @param z Array of nCount z values.* @param pabSuccess Output array of nCount value that will be set to TRUE/FALSE* @return TRUE or FALSE*/
int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,int *pabSuccess ){// Prevent any coordinate modification when possibleif ( bNoTransform ){if( pabSuccess ){for( int i = 0; i < nCount; i++ ){pabSuccess[i] = TRUE;}}return TRUE;}// Workaround potential bugs in proj.4 such as// the one of https://github.com/OSGeo/proj.4/commit///                              bc7453d1a75aab05bdff2c51ed78c908e3efa3cdfor( int i = 0; i < nCount; i++ ){if( CPLIsNan(x[i]) || CPLIsNan(y[i]) ){x[i] = HUGE_VAL;y[i] = HUGE_VAL;}}/* -------------------------------------------------------------------- */
/*      Potentially transform to radians.                               */
/* -------------------------------------------------------------------- */if( bSourceLatLong ){if( bSourceWrap ){for( int i = 0; i < nCount; i++ ){if( x[i] != HUGE_VAL && y[i] != HUGE_VAL ){if( x[i] < dfSourceWrapLong - 180.0 )x[i] += 360.0;else if( x[i] > dfSourceWrapLong + 180 )x[i] -= 360.0;}}}for( int i = 0; i < nCount; i++ ){if( x[i] != HUGE_VAL ){x[i] *= dfSourceToRadians;y[i] *= dfSourceToRadians;}}}/* -------------------------------------------------------------------- */
/*      Optimized transform from WebMercator to WGS84                   */
/* -------------------------------------------------------------------- */bool bTransformDone = false;if( bWebMercatorToWGS84 ){static const double REVERSE_SPHERE_RADIUS = 1.0 / 6378137.0;double y0 = y[0];for( int i = 0; i < nCount; i++ ){if( x[i] != HUGE_VAL ){x[i] = x[i] * REVERSE_SPHERE_RADIUS;if( x[i] > M_PI ){if( x[i] < M_PI+1e-14 ){x[i] = M_PI;}else if( bCheckWithInvertProj ){x[i] = HUGE_VAL;y[i] = HUGE_VAL;y0 = HUGE_VAL;continue;}else{do {x[i] -= 2 * M_PI;} while( x[i] > M_PI );}}else if( x[i] < -M_PI ){if( x[i] > -M_PI-1e-14 ){x[i] = -M_PI;}else if( bCheckWithInvertProj ){x[i] = HUGE_VAL;y[i] = HUGE_VAL;y0 = HUGE_VAL;continue;}else{do {x[i] += 2 * M_PI;} while( x[i] < -M_PI );}}// Optimization for the case where we are provided a whole line// of same northing.if( i > 0 && y[i] == y0 )y[i] = y[0];elsey[i] =M_PI / 2.0 -2.0 * atan(exp(-y[i] * REVERSE_SPHERE_RADIUS));}}bTransformDone = true;}else if( bIdentityTransform ){bTransformDone = true;}/* -------------------------------------------------------------------- */
/*      Do the transformation (or not...) using PROJ.4.                 */
/* -------------------------------------------------------------------- */if( !bTransformDone && pjctx == NULL ){// The mutex has already been created.CPLAssert(hPROJMutex != NULL);CPLAcquireMutex(hPROJMutex, 1000.0);}int err = 0;if( bTransformDone ){// err = 0;}else if( bCheckWithInvertProj ){// For some projections, we cannot detect if we are trying to reproject// coordinates outside the validity area of the projection. So let's do// the reverse reprojection and compare with the source coordinates.if( nCount > nMaxCount ){nMaxCount = nCount;padfOriX = static_cast<double*>(CPLRealloc(padfOriX, sizeof(double) * nCount));padfOriY = static_cast<double*>(CPLRealloc(padfOriY, sizeof(double)*nCount));padfOriZ = static_cast<double*>(CPLRealloc(padfOriZ, sizeof(double)*nCount));padfTargetX = static_cast<double*>(CPLRealloc(padfTargetX, sizeof(double)*nCount));padfTargetY = static_cast<double*>(CPLRealloc(padfTargetY, sizeof(double)*nCount));padfTargetZ = static_cast<double*>(CPLRealloc(padfTargetZ, sizeof(double)*nCount));}memcpy(padfOriX, x, sizeof(double) * nCount);memcpy(padfOriY, y, sizeof(double) * nCount);if( z ){memcpy(padfOriZ, z, sizeof(double)*nCount);}err = pfn_pj_transform( psPJSource, psPJTarget, nCount, 1, x, y, z );if( err == 0 ){memcpy(padfTargetX, x, sizeof(double) * nCount);memcpy(padfTargetY, y, sizeof(double) * nCount);if( z ){memcpy(padfTargetZ, z, sizeof(double) * nCount);}err = pfn_pj_transform( psPJTarget, psPJSource , nCount, 1,padfTargetX, padfTargetY,z ? padfTargetZ : NULL);if( err == 0 ){for( int i = 0; i < nCount; i++ ){if( x[i] != HUGE_VAL && y[i] != HUGE_VAL &&(fabs(padfTargetX[i] - padfOriX[i]) > dfThreshold ||fabs(padfTargetY[i] - padfOriY[i]) > dfThreshold) ){x[i] = HUGE_VAL;y[i] = HUGE_VAL;}}}}}else{err = pfn_pj_transform( psPJSource, psPJTarget, nCount, 1, x, y, z );}/* -------------------------------------------------------------------- */
/*      Try to report an error through CPL.  Get proj.4 error string    */
/*      if possible.  Try to avoid reporting thousands of errors.       */
/*      Suppress further error reporting on this OGRProj4CT if we       */
/*      have already reported 20 errors.                                */
/* -------------------------------------------------------------------- */if( err != 0 ){if( pabSuccess )memset( pabSuccess, 0, sizeof(int) * nCount );if( m_bEmitErrors && ++nErrorCount < 20 ){if( pjctx != NULL )// pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0.CPLAcquireMutex(hPROJMutex, 1000.0);const char *pszError = NULL;if( pfn_pj_strerrno != NULL )pszError = pfn_pj_strerrno( err );if( pszError == NULL )CPLError( CE_Failure, CPLE_AppDefined,"Reprojection failed, err = %d",err );elseCPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );if( pjctx != NULL )// pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0.CPLReleaseMutex(hPROJMutex);}else if( nErrorCount == 20 ){CPLError( CE_Failure, CPLE_AppDefined,"Reprojection failed, err = %d, further errors will be ""suppressed on the transform object.",err );}if( pjctx == NULL )CPLReleaseMutex(hPROJMutex);return FALSE;}if( !bTransformDone && pjctx == NULL )CPLReleaseMutex(hPROJMutex);/* -------------------------------------------------------------------- */
/*      Potentially transform back to degrees.                          */
/* -------------------------------------------------------------------- */if( bTargetLatLong ){for( int i = 0; i < nCount; i++ ){if( x[i] != HUGE_VAL && y[i] != HUGE_VAL ){x[i] *= dfTargetFromRadians;y[i] *= dfTargetFromRadians;}}if( bTargetWrap ){for( int i = 0; i < nCount; i++ ){if( x[i] != HUGE_VAL && y[i] != HUGE_VAL ){if( x[i] < dfTargetWrapLong - 180.0 )x[i] += 360.0;else if( x[i] > dfTargetWrapLong + 180 )x[i] -= 360.0;}}}}/* -------------------------------------------------------------------- */
/*      Establish error information if pabSuccess provided.             */
/* -------------------------------------------------------------------- */if( pabSuccess ){for( int i = 0; i < nCount; i++ ){if( x[i] == HUGE_VAL || y[i] == HUGE_VAL )pabSuccess[i] = FALSE;elsepabSuccess[i] = TRUE;}}return TRUE;
}
gdal-2.2.2\ogr\ogr_spatialref.h
/************************************************************************/
/*                     OGRCoordinateTransformation                      */
/*                                                                      */
/*      This is really just used as a base class for a private          */
/*      implementation.                                                 */
/************************************************************************//*** Interface for transforming between coordinate systems.** Currently, the only implementation within OGR is OGRProj4CT, which* requires the PROJ.4 library to be available at run-time.** Also, see OGRCreateCoordinateTransformation() for creating transformations.*/class CPL_DLL OGRCoordinateTransformation
{}

待继续分析列表:

9、earth文件中都有哪些options((九)中问题)

10、如何根据earth文件options创建不同的地理信息引擎节点((九)中问题)

11、rex地理信息引擎的四梁八柱((九)中问题)

12、osgEarth::TerrainEngineNode中setMap方法作用((十二)中问题)

13、RexTerrainEngineNode中_mapFrame的作用((十二)中问题)

14、地形变形(Terrain morphing)((十二)中问题)

15、地球瓦片过期门限的含义((十二)中问题)

16、高分辨率优先的含义((十二)中问题)

17、OSGEARTH_DEBUG_NORMALS环境变量的作用((十二)中问题)

18、活跃瓦片寄存器的作用((十二)中问题)

19、资源释放器子节点的作用((十二)中问题)

20、共享几何图形池子节点的作用((十二)中问题)

21、分页瓦片加载器子节点的作用((十二)中问题)

22、分页瓦片卸载器子节点的作用((十二)中问题)

23、栅格化器子节点的作用((十二)中问题)

24、地形子节点的作用((十二)中问题)

25、绑定渲染器的作用((十二)中问题)

26、地图回调函数的作用((十二)中问题)

27、如何将地图图层添加到rex引擎中((十二)中问题)

28、选择信息的作用((十二)中问题)

29、瓦片包围盒修改回调函数的作用((十二)中问题)

30、刷新rex引擎((十二)中问题)

31、刷新边界作用((十二)中问题)

32、osgEarth::Metrics类的意义((十四)中问题)

33、请求合并队列_mergeQueue((十四)中问题)

34、分页瓦片加载器在更新遍历时对请求处理过程((十四)中问题)

35、分页瓦片加载器在更新遍历时对已处理请求裁剪过程((十四)中问题)

36、已处理的请求队列_requests((十四)中问题)

37、DatabasePager中的_fileRequestQueue和_httpRequestQueue((十六)中问题)

38、瓦片请求的生成到处理过程详解((十六)中问题)

39、瓦片节点TileNode的创建过程((十七)中问题)

40、request请求加载瓦片优先级的含义((十七)中问题)

41、request的_internalHandle的作用((十七)中问题)

42、DatabaseRequest中_objectCache含义((十七)中问题)

42、osgEarth的多线程分析((十七)中问题)

43、osgEarth的缓存及其结构((十七)中问题)

44、DatabaseThread从缓存加载数据过程((十七)中问题)

45、DatabaseThread从文件加载数据过程((十七)中问题)

46、决定创建TileNode的时机条件((十七)中问题)

47、TerrainEngineNode的createTileModel过程详解((十七)中问题)

48、DatabaseThread中CompileSet的含义((十七)中问题)

48、PagerLoader的traverse过程详解((十七)中问题)

49、DatabaseThread的run过程详解((十七)中问题)

50、LoadTileData的invoke过程详解((十七)中问题)

51、TileNode的cull过程详解((十七)中问题)

52、遮罩生成器osgEarth::Drivers::RexTerrainEngine::MaskGenerator((十八)中问题)

53、RexTerrainEngineNode::traverse过程详解((十八)中问题)

54、TileNode节点下的场景树分析((十八)中问题)

55、地形瓦片大小尺寸和LOD的关系((十八)中问题)

56、TileNode的_tileKeyValue作用((十八)中问题)

57、TileNode的_morphConstants作用((十八)中问题)

58、TileNode的_stitchNormalMap作用((十八)中问题)

59、TileNode的_renderModel作用((十八)中问题)

60、初始化高程栅格过程详解((十八)中问题)

61、LoadTileData中的CreateTileModelFilter作用((十八)中问题)

62、TileNode节点何时会从场景树中移除((十八)中问题)

63、osgEarth::Map的Profile创建过程((二十)中问题)

64、osgEarth::TerrainTileModelFactory添加颜色层和影像层的区别((二十一)中问题)

65、osgEarth::PatchLayer修补层的作用((二十一)中问题)

66、osgEarth::TerrainLayer中的_memCache(osgEarth::MemCache)详解((二十一)中问题)

67、osgEarth::Layer::RenderType图层渲染类型的作用((二十一)中问题)

68、osgEarth::TerrainLayer中TileSource的作用((二十一)中问题)

69、earth文件没有设置高程图层会不会有默认高程层(高程均为0)((二十一)中问题)

70、TerrainTileModelFactory::addColorLayers过程详解((二十一)中问题)

71、TerrainTileModelFactory::addElevation过程详解((二十一)中问题)

72、osgearth中可能用到的几个全局实例对象(osgDB::Registry osgEarth::Registry osg::Timer osg::DisplaySetting)((二十三)中问题)

73、osgEarth::Map::addLayer过程详解((二十三)中问题)

74、TileNode::setDirty过程详解((二十三)中问题)

75、请求四个状态的含义(IDLE RUNNING MERGING FINISHED)((二十三)中问题)

76、什么时候删除TileNode节点,不会一直增加吧((二十三)中问题)

77、寄存器中请求状态活动记录的含义Registry::instance()->endActivity( req->getName() )((二十三)中问题)

78、瓦片TileNode的生命周期流程详解((二十三)中问题)

79、rex引擎如何将瓦片构造成地球形状((二十五)中问题)

80、高程、影像文件格式详解((二十五)中问题)

81、TileNode的merge过程详解((二十六)中问题)

82、osgEarth支持的空间参考坐标系详解(osgEarth::SpatialReference、osgEarth::CubeSpatialReference、osgEarth::TangentPlaneSpatialReference)((二十九)中问题)

83、osgEarth地球椭球体ellipsoid 大地基准面datum 地图投影Projection详解((二十九)中问题)

84、空间参考坐标系和坐标系统类型的关系(geocentric projected)((二十九)中问题)

85、proj4是什么((二十九)中问题)

86、为什么要删除设置过的垂直水准面((二十九)中问题)

87、osgEarth如何对投影坐标系和大地坐标系进行显示处理的((二十九)中问题)

88、TileNode的节点构成,一个surface、tilenode((三十)中问题)

89、MapFram和MapInfo的关系((三十)中问题)

90、ModifyBoundingBoxCallback的使用时机和场合((三十)中问题)

91、MapFrame为什么要单独存放高程层_elevationLayers,而不是放在图层_layers中((三十)中问题)

92、MapFrame和Map中高程池的作用osg::ref_ptr<ElevationPool> _elevationPool((三十)中问题)

93、osgEarth::Drivers::RexTerrainEngine::TileDrawable分析((三十)中问题)

94、请求读取地理信息失败会如何处理((三十二)中问题)

95、RexTerrainEngineNode的遍历过程详解((三十三)中问题)

96、osgEarth::Drivers::RexTerrainEngine::TerrainCuller的apply过程详解((三十三)中问题)

97、RexTerrainEngineNode的updateState过程详解 设置了很多着色器变量((三十三)中问题)

98、什么时候分配opengl资源((三十三)中问题)

99、TileNode释放opengl资源过程releaseGLObjects详解((三十三)中问题)

100、最近一次遍历的帧号和时间是怎么设置呢(在渲染遍历里),怎么就不会再渲染遍历该瓦片节点了((三十三)中问题)

101、osg::State和osg::StateSet的关系((三十四)中问题)

102、osgEarth::SpatialReference和osgEarth::Profile的关系((三十六)中问题)

103、osgEarth的Geographic、Geodetic、Geocentric和Project的关系((三十六)中问题)

104、TileNode绘制过程详解((三十七)中问题)

105、如何控制父子TileNode节点的显隐((三十七)中问题)

106、GeometryPool的createGeometry过程详解((三十七)中问题)

107、TileNode如何从地图中提取与其分辨率相适应的图像数据((三十七)中问题)

108、如何定制椭球体并进行椭球体间坐标转换((四十五)中问题)

109、Horizon Cull是什么意思((四十五)中问题)

110、osgEarth::Drivers::RexTerrainEngine::DrawState的作用((四十五)中问题)

111、osgEarth的线程分析((四十五)中问题)

112、从osgEarth到osg到Opengl((四十五)中问题)

113、osg::Program与osgEarth::VirtualProgram的关系((四十五)中问题)

114、rex引擎shader文件中的#pragma vp_entryPoint vp_location等含义((四十五)中问题)

115、rex引擎的着色器如何区分顶点和片段((四十五)中问题)

116、osg::Program是如何对着色器及其变量进行管理的((四十五)中问题)

117、osg的窗口是如何与opengl集成的((四十五)中问题)

118、osg是如何实现opengl的初始化的((四十五)中问题)

119、CGCS2000余WGS84坐标系的比较((四十六)中问题)

120、着色器代码文件到着色器程序的过程((五十一)中问题)

121、osgEarth::VirtualProgram默认出现在哪些位置((五十一)中问题)

122、rex引擎默认的几个着色器功能分析((五十一)中问题)

123、osgEarth::TileRasterizer功能详解((五十二)中问题)

124、osgEarth::ImageLayer如何使用VirtualProgram((五十二)中问题)

125、osgEarth::ShaderFactory osgEarth::ShaderLoader关系((五十四)中问题)

126、osgEarth::URI和osgEarth::URIContext的作用((五十四)中问题)

127、RexTerrainEngineNode中_renderBindings的作用((五十四)中问题)

128、Rex引擎如何给shader文件中的uniform变量赋值((五十四)中问题)

129、osgEarth中多个着色器的源代码的编译链接过程((五十四)中问题)

130、osgEarth::ShaderFactory osgEarth::ShaderLoader关系((五十四)中问题)

131、TileNode与DrawTileCommand的关系((五十五)中问题)

132、如何提取出指定范围的高程网格((五十五)中问题)

133、从earth文件加载高层图层的过程((五十五)中问题)

134、TerrainTileModel与TileRenderModel的关系((五十五)中问题)

135、EngineContext的作用((五十五)中问题)

136、几个uniformmap的关系((五十五)中问题)

137、DrawTileCommand中的采样器((五十五)中问题)

138、TileNode中的_surface(SurfaceNode)作用是什么((五十五)中问题)

139、stateset中的adduniform、setTextureAttribute等最后是如何反应到opengl上的((五十五)中问题)

140、状态树和渲染树的关系((五十五)中问题)

141、TileRenderModel中的RenderingPass和RenderBindings((五十五)中问题)

142、高程瓦片的绘制过程((五十五)中问题)

143、如何从高程影像变成高程网格((七十一)中问题)

144、osg::StateSet中的_binMode作用((七十二)中问题)

145、rex的瓦片高程影像和高程文件中的影像尺寸如何对应((七十二)中问题)

146、osgEarth::TerrainLayerOptions高程层选项中参数的含义((七十二)中问题)

147、从高程文件读取的高程信息如何填充rex的高程瓦片((七十二)中问题)

148、地图下载器实现原理((七十二)中问题)

osgEarth的Rex引擎原理分析(七十三)从高程文件读取的高程信息如何填充rex的高程瓦片相关推荐

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

    目标:(一二五)中问题212 通过如下确定瓦片的组织方式 ,核心是profile osgEarth/Map.cpp void Map::calculateProfile() {// collect t ...

  2. osgEarth的Rex引擎原理分析(七十九)如何加载百度、高德、谷歌、微软的在线地图

    目标:(七十八)中的问题155 瓦片生成后,就是一堆图片.怎么对这堆图片进行编号,是目前主流互联网地图商分歧最大的地方.总结起来分为四个流派: 谷歌XYZ:Z表示缩放层级,Z=zoom:XY的原点在左 ...

  3. osgEarth的Rex引擎原理分析(九十)如何设置高度单位(m、km等)

    目标:(八十二)中的问题160 默认的单位是m,如果要修改为其它单位,需要直接修改profile文件,或者设置缩放比例 <profile srs="+proj=merc +a=6378 ...

  4. osgEarth的Rex引擎原理分析(一二五)着色器源代码加工处理过程

    目标:(一二四)中问题211 1.添加默认着色器 这类着色器源代码是内置在程序里的,不会经过osgEarth着色器框架的整合. 1.1加载时处理 osg/StateSet.cppstatic cons ...

  5. osgEarth的Rex引擎原理分析(一二四)osgEarth着色器文件与场景树节点的对应关系

    目标:(一二三)中问题210 场景树 rex | terrain-------------------------------------------------------------------- ...

  6. osgEarth的Rex引擎原理分析(九十五)地形变形(Terrain morphing)

    目标:(十二)中的问题14 morphing翻译为渐变(或混合)比较合适. 先看两张图,左图是使用了Image morphing,右图没有使用.morph的作用是使视域边界处的瓦片颜色和高程均匀变化. ...

  7. osgEarth的Rex引擎原理分析(一零九)19级瓦片分辨率估算

    目标:(一零八)中的问题194 rex的瓦片分级为0.1.....19 第0级角度分辨率 180° 第1级角度分辨率 180°/2 ... 第19级角度分辨率 180°/2^19=0.00034332 ...

  8. osgEarth的Rex引擎原理分析(四十三)osgEarth的Geographic、Geodetic、Geocentric和Project的关系

    目标:(三十六)中的103 Geographic采用经纬高,高度是平均海平面高(需要有垂直水准面辅助) Geodetic采用经纬高,高度是相对椭球体的法线高 ECEF(也即Geocentric)采用地 ...

  9. osgEarth的Rex引擎原理分析(二十五)地形瓦片大小尺寸和LOD的关系

    目标:(十八)中的问题55 osgEarth::TerrainOption中_tileSize默认大小为17,LOD的默认范围为0-23,这两个值的关系是什么? 还有瓦片的像素尺寸_tilePixel ...

最新文章

  1. 最长回文子串-三种DP实现
  2. Linux-sed文本处理流编辑器
  3. ML:MLOps系列讲解之《CRISP-ML (Q)ML生命周期过程—了解机器学习开发的标准过程模型—业务和数据理解→数据工程(数据准备)→ML模型工程→评估ML模型→模型部署→模型监控和维护》解读
  4. 2016 年 Linux 领域的十大新闻,你有关注吗?
  5. 一次竞赛案例的分享——基于正则表达式的深度学习应用
  6. Android中关于线性布局基线对齐的讲述
  7. java8 :: 用法 (JDK8 双冒号用法)
  8. sqlserver存储过程入门之 游标
  9. 在自定义HttpHandler中如何使用Session
  10. [css] 头部设置meta也可以做到自适应为啥还要用rem?
  11. c# 保存和打开文件的方法
  12. 化解恶劣情绪山人自有妙计
  13. [译]简单声明Lua类
  14. 2019年9月全国程序员工资统计,你处于什么位置?
  15. 渲梦工厂V2.1.5.0简体中文官方版,作图快10倍~
  16. 7.13建行天津实习面经
  17. 华为硬件工程师社招机考题库_华为硬件工程师笔试题
  18. Lan9252-FPGA调试笔记
  19. 鼠标点击网页空白处出现手机号
  20. mmap和mmap64

热门文章

  1. 黑马程序员-01.IOS和MAC OS X简介总结
  2. GridSearchCV实例:对Xgboost回归任务进行网格调参
  3. kinect V2 驱动安装说明
  4. 浙江污水处理厂数字孪生平台建模_三维激光扫描_吉优赛维三维可视化管理平台_三维建模_3D模型
  5. 关于利用postman来模拟并发请求
  6. Html和css 两张图片叠加一起
  7. FreeRTOS学习笔记【二】——FreeRTOS 移植
  8. 一个ACM底层参赛选手的退役感言
  9. 【PCB硬件】PCB布线规范技巧
  10. AD——PCB布线实用技巧