在FlatteningLayer文件的createHeightField函数中:使用的github在2017年1月份的代码

if (!geoms.getComponents().empty())
{
osg::ref_ptr<osg::HeightField> hf = HeightFieldUtils::createReferenceHeightField(
ex,
, , // base tile size for elevation data
0u, // no border
true); // initialize to HAE (0.0) heights // Initialize to NO DATA.
hf->getFloatArray()->assign(hf->getNumColumns()*hf->getNumRows(), NO_DATA_VALUE); // Create an elevation query envelope at the LOD we are creating
osg::ref_ptr<ElevationEnvelope> envelope = _pool->createEnvelope(workingSRS, key.getLOD()); // Resolve the buffering widths:
double lineWidthLocal = lineWidth()->as(workingSRS->getUnits());
double bufferWidthLocal = bufferWidth()->as(workingSRS->getUnits()); if(integrate(key, hf, &geoms, workingSRS, lineWidthLocal, bufferWidthLocal, envelope, progress) || (progress && progress->isCanceled()))
{
//double t_create = OE_GET_TIMER(create);
//OE_INFO << LC << key.str() << " : t=" << t_create << "s\n"; // If integrate made any changes, return the new heightfield.
// (Or if the operation was canceled...return it anyway and it
// will be discarded).
return hf.release();
}
}

 创建一个高度场,长宽都是257,边界为0,高度引用大地水平基准面。

用默认值初始化高度场

在自己创建的LOD中创建一个高程查询信

解决缓存宽度

整合新高程

如果高程有任何改变,返回新的高程图,高度场。

这里integrate调用的函数,调用了integratePolygons函数来创建平整的高程图,我们看看这里具体怎么操作的

我们来看integratePolygons函数:

 // Creates a heightfield that flattens an area intersecting the input polygon geometry.创建一个包含集合多边形的高度场
// The height of the area is found by sampling a point internal to the polygon.
// bufferWidth = width of transition from flat area to natural terrain.
bool integratePolygons(const TileKey& key, osg::HeightField* hf, const Geometry* geom, const SpatialReference* geomSRS,
double bufferWidth, ElevationEnvelope* envelope, ProgressCallback* progress)
{
bool wroteChanges = false; const GeoExtent& ex = key.getExtent(); double col_interval = ex.width() / (double)(hf->getNumColumns()-);
double row_interval = ex.height() / (double)(hf->getNumRows()-); POINT Pex, P, internalP; bool needsTransform = ex.getSRS() != geomSRS;

循环遍历长宽间隔获取每个顶点坐标

         for (unsigned col = ; col < hf->getNumColumns(); ++col)
{
Pex.x() = ex.xMin() + (double)col * col_interval; for (unsigned row = ; row < hf->getNumRows(); ++row)
{
// check for cancelation periodically
//if (progress && progress->isCanceled())
// return false; Pex.y() = ex.yMin() + (double)row * row_interval; if (needsTransform)
ex.getSRS()->transform(Pex, geomSRS, P);
else
P = Pex; bool done = false;
double minD2 = bufferWidth * bufferWidth; // minimum distance(squared) to closest polygon edge const Polygon* bestPoly = 0L; ConstGeometryIterator giter(geom, false);
while (giter.hasMore() && !done)
{
const Polygon* polygon = dynamic_cast<const Polygon*>(giter.next());
if (polygon)
{
// Does the point P fall within the polygon?
循环检查这里是否有点在这些几何形状里
if (polygon->contains2D(P.x(), P.y()))
{
// yes, flatten it to the polygon's centroid elevation;
// and we're dont with this point.
如果这点就在几何形状范围里,直接跳出检查
done = true;
bestPoly = polygon;
minD2 = -1.0;
} // If not in the polygon, how far to the closest edge?
如果没在,计算距离边缘最近的距离的平方
                         else
{
double D2 = getDistanceSquaredToClosestEdge(P, polygon);
查看获得值是否在缓存范围内
if (D2 < minD2)
{
如果在范围内,就设置好这个点在缓存内最近的位置,以便后面计算
minD2 = D2;
bestPoly = polygon;
}
}
}
} if (bestPoly && minD2 != 0.0)
{

  判断这些需要获取的高程点,有没有在需要关注的几何图形里或者缓冲区范围内的,如果有就做以下工作,来抬高地形:

                     float h;
POINT internalP = getInternalPoint(bestPoly);
float elevInternal = envelope->getElevation(internalP.x(), internalP.y()); if (minD2 < 0.0)
{
h = elevInternal;
}
else
{
float elevNatural = envelope->getElevation(P.x(), P.y());
double blend = clamp(sqrt(minD2)/bufferWidth, 0.0, 1.0); // [0..1] 0=internal, 1=natural
h = smoothstep(elevInternal, elevNatural, blend);
} hf->setHeight(col, row, h);
wroteChanges = true;
} }
} return wroteChanges;
}

真正平整的函数在:integrate函数

进入FlatteningLayer文件的integratePolygons函数

先获取TileKey范围

获取长宽的间隔分别是多大长度

检查是否要做SRS转换,这里看是需要的

West -180  xMin    SRS-> -20037508.343

East  0     xMax

South -90  xMin    SRS-> -20037508.343

North 90    yMax

循环遍历长宽间隔获取每个顶点坐标

POINT P是这点的世界位置点

循环检查这些几何形状

看看点是否在这些几何形状里

如果不在,计算距离边缘最近的距离的平方

查看获得值是否在平整范围内

如果在范围内,就设置好这个点在范围内最近的位置,以便后面计算

如果点就在几何形状范围里,直接跳出检查

直接点说

就是判断这些需要获取的高程点,有没有在需要关注的几何图形里或者缓冲区范围内的,如果有就做以下工作,来抬高地形:

先找到几何图形内部的一个顶点(多为中心,质心等)

通过ElevationEnvelope类的getElevation函数计算这个点的高程

判断这个要改变高程的点与几何图形的位置关系:

如果在几何图形内就设置这个点用刚才获取的高程点(这个方式有待商榷)

如果在缓冲区上,获取这个点的现实高程值。获取当前点在缓冲区上的范围值,做smoothstep变换。

然后将之前得到的高程按格子塞入高程图。

齐活!

[原][osgearth]OE地形平整代码解读的更多相关文章

  1. OSGEARTH三维地形开源项目

    第一章   OSGEarth介绍 第二章   OSGEarth编译环境配置 OSGEarth的编译环境配置随着版本的不同.运行平台的不同,也有很大的差异.本章主要以Windows XP SP3(x86 ...

  2. 【dlib代码解读】人脸检测器的训练【转】

    转自:http://blog.csdn.net/elaine_bao/article/details/53046542 版权声明:本文为博主原创文章,转载请注明.   目录(?)[-] 综述 代码解读 ...

  3. 13.Ext.extend用法以及代码解读

    转自:http://www.blogjava.net/dragonshrimp/archive/2008/03/01/183060.html Ext.extend用法以及代码解读 概述 Ext.ext ...

  4. Android MVP模式 谷歌官方代码解读

    Google官方MVP Sample代码解读 关于Android程序的构架, 当前(2016.10)最流行的模式即为MVP模式, Google官方提供了Sample代码来展示这种模式的用法. Repo ...

  5. 优秀开源代码解读之JS与iOS Native Code互调的优雅实现方案

    简介 本篇为大家介绍一个优秀的开源小项目:WebViewJavascriptBridge. 它优雅地实现了在使用UIWebView时JS与ios 的ObjC nativecode之间的互调,支持消息发 ...

  6. SoftmaxLayer and SoftmaxwithLossLayer 代码解读

    SoftmaxLayer and SoftmaxwithLossLayer 代码解读 Wang Xiao 先来看看 SoftmaxWithLoss 在prototext文件中的定义: layer { ...

  7. Hybrid----优秀开源代码解读之JS与iOS Native Code互调的优雅实现方案-备

    本篇为大家介绍一个优秀的开源小项目:WebViewJavascriptBridge. 它优雅地实现了在使用UIWebView时JS与ios 的ObjC nativecode之间的互调,支持消息发送.接 ...

  8. Jsoup代码解读之六-防御XSS攻击

    Jsoup代码解读之八-防御XSS攻击 防御XSS攻击的一般原理 cleaner是Jsoup的重要功能之一,我们常用它来进行富文本输入中的XSS防御. 我们知道,XSS攻击的一般方式是,通过在页面输入 ...

  9. Jsoup代码解读之五-实现一个CSS Selector

    Jsoup代码解读之七-实现一个CSS Selector 当当当!终于来到了Jsoup的特色:CSS Selector部分.selector也是我写的爬虫框架webmagic开发的一个重点.附上一张s ...

随机推荐

  1. C++ 入门随手笔记及联系

    一.第一个C++程序 1.文件扩展名  C++源代码的文件扩展名.cpp.C.cxx.c(需要指定编译语言)  自定义的头文件依然保留.h 2.头文件  C++标准库的头文件不带.h,最常用的是ios ...

  2. 浅析Oracle 12c中Data Guard新特性

    浅析Oracle 12c中Data Guard新特性   写在前面 无论是做Oracle运维的小伙伴还是老伙伴,想必对Oracle数据库的数据级灾备核心技术—Data Guard是再熟悉不过了!这项从 ...

  3. Exchange & Office 365最小混合部署

    前言 这篇文章的主题是混合部署~ 混合使得本地组织和云环境像一个单一的.协作紧密的组织一样运作.当组织决定进行混合部署,达到本地Exchange Server和Office 365共存的状态时,就会面 ...

  4. HDFS NameNode内存全景

    一.概述 从整个HDFS系统架构上看,NameNode是其中最重要.最复杂也是最容易出现问题的地方,而且一旦NameNode出现故障,整个Hadoop集群就将处于不可服务的状态,同时随着数据规模和集群 ...

  5. Logstash和Flume-NG Syslog接收小测试

    目前在大规模日志处理平台中常见的日志采集器可以采用Logstash或Flume.这两种日志采集器架构设计理念基本相似,都采用采集-过滤处理-输出的方式.下面对这两种采集器Syslog接收性能做个简单测 ...

  6. linux下统计目录下所有子目录的大小

    du -sh * --exclude=tar |awk '{v=substr($1,length($1),1)}v=="G"{$0="1G "$0}v==&qu ...

  7. JQuery Mobile+JS实现智能浮动定位导航条

    实现原理 主要用到几个知识点: 什么是scrollTop? CSS position定位 判断是否为IE6浏览器 元素相对于窗口的距离 原理:1,浏览器向下滚动时,当document的scrollTo ...

  8. Django在admin模块中显示auto_now_add=True或auto_now=True的时间类型列

    转载自: http://www.tuicool.com/articles/ZryE7f 在Django如果model中的列定义了auto_now_add或auto_now属性,那么这种列不会在admi ...

  9. Python:numpy.newaxis

    x1[:,np.newaxis]:增维,转置 从字面上是插入新的维度的意思 demo1: 针对一维的情况 >>> b = np.array([1, 2, 3, 4, 5, 6]) & ...

  10. centos 系统安装基本步骤,面试必考

    1.调整开机媒体,通常为cd或者dvd,也可以是u盘. 2.选择安装模式,是否需要图形化 3.语系及键盘语系选择 4.软件选择 5.磁盘分区操作,主+扩展分区最多4个.逻辑分区在扩展分区下建立 6.时 ...