• World Wind Java开发之十——AnalyticSurface栅格渲染(转)


    http://blog.csdn.net/giser_whu/article/details/43017881

    1、AnalyticSurfaceDemo

    ArcGIS下对栅格的各种分级渲染效果是非常好的,可以做出很漂亮的图,现在在WW下也可以做出同样的效果了,看到这里是不是有点小兴奋呢。先看下WW自带的AnalyticSurfaceDemo的运行效果图:

    通过看源代码可以知道给出了三种渲染示例,其中两种是动态的,这里我需要的是对dem数据或者是单波段影像的渲染,也就是左上方的渲染效果。

    2、AnalyticSurface类

    下面来看下主要用到的类:

    主要用到的方法:

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. // 创建AnalyticSurface并设置其属性  
    2.         final AnalyticSurface surface = new AnalyticSurface();  
    3.         surface.setSector(raster.getSector());  
    4.         surface.setDimensions(raster.getWidth(), raster.getHeight());  
    5.         surface.setValues(AnalyticSurface.createColorGradientValues(  
    6.                 raster.getBuffer(), raster.getTransparentValue(), extremes[0],  
    7.                 extremes[1], minHue, maxHue));  
    8.         // surface.setVerticalScale(5e3);  
    9.         // 设置表面渲染方式为 CLAMP_TO_GROUND  
    10.         surface.setAltitudeMode(WorldWind.CLAMP_TO_GROUND);  
    根据自己的需要可以查阅开发文档设置其他属性。

    3、DEM渲染实例

    将demo中的代码稍加修改封装为AnalyticSurfaceUtil类以供后面所有栅格数据的渲染使用,目前比较简单,后面陆续扩充该类。
    WW下渲染效果:
    ArcMap下渲染效果:

    可以看到WW下渲染的效果丝毫不逊色,图是不是很漂亮呢。

    4、洪涝模拟渲染

    这是对之前洪涝模拟的改进,对洪涝模拟输出的范围图和深度图进行渲染。
    (1)范围图
    (2)深度图
    这幅渲染的深度图是不是有种火山喷发的感觉,很有艺术美感,非常喜欢这个渲染的效果。改一下配色再看下另一种渲染效果:

    5、源码。

    下面是自己封装的AnalyticSurfaceUtil类,供大家参考:
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. /** 
    2.  * @Copyright 2014-2020 @刘硕 
    3.  **/  
    4.   
    5. package edu.whu.vge.util;  
    6.   
    7. import gov.nasa.worldwind.WorldWind;  
    8. import gov.nasa.worldwind.avlist.AVKey;  
    9. import gov.nasa.worldwind.avlist.AVList;  
    10. import gov.nasa.worldwind.data.BufferWrapperRaster;  
    11. import gov.nasa.worldwind.data.DataRaster;  
    12. import gov.nasa.worldwind.data.DataRasterReader;  
    13. import gov.nasa.worldwind.data.DataRasterReaderFactory;  
    14. import gov.nasa.worldwind.exception.WWRuntimeException;  
    15. import gov.nasa.worldwind.geom.Extent;  
    16. import gov.nasa.worldwind.geom.Sector;  
    17. import gov.nasa.worldwind.layers.RenderableLayer;  
    18. import gov.nasa.worldwind.render.DrawContext;  
    19. import gov.nasa.worldwind.render.Renderable;  
    20. import gov.nasa.worldwind.util.Logging;  
    21. import gov.nasa.worldwind.util.WWBufferUtil;  
    22. import gov.nasa.worldwind.util.WWIO;  
    23. import gov.nasa.worldwind.util.WWMath;  
    24. import gov.nasa.worldwindx.examples.analytics.AnalyticSurface;  
    25. import gov.nasa.worldwindx.examples.analytics.AnalyticSurfaceAttributes;  
    26. import gov.nasa.worldwindx.examples.analytics.AnalyticSurfaceLegend;  
    27. import gov.nasa.worldwindx.examples.util.ExampleUtil;  
    28.   
    29. import java.awt.Point;  
    30. import java.io.File;  
    31. import java.text.DecimalFormat;  
    32. import java.text.FieldPosition;  
    33. import java.text.Format;  
    34.   
    35. import javax.swing.SwingUtilities;  
    36.   
    37. /** 
    38.  * @项目名称:SmartScope 
    39.  * @类名称:AnalyticSurfaceUtil 
    40.  * @类描述: 
    41.  * @创建人:刘硕 
    42.  * @创建时间:2015-1-21 下午3:40:54 
    43.  * @修改备注: 
    44.  * @版本: 
    45.  */  
    46.   
    47. public class AnalyticSurfaceUtil  
    48. {  
    49.   
    50.     /** 
    51.      * 创建一个新的实例 AnalyticSurfaceUtil. 
    52.      *  
    53.      */  
    54.     public AnalyticSurfaceUtil()  
    55.     {  
    56.         // TODO Auto-generated constructor stub  
    57.     }  
    58.   
    59.     public static void createPrecipitationSurface(double minHue, double maxHue,  
    60.             final RenderableLayer outLayer)  
    61.     {  
    62.         String DATA_PATH = "J:/data/wwj/FloodDepth.tif";  
    63.         BufferWrapperRaster raster = loadRasterElevations(DATA_PATH);  
    64.         if (raster == null)  
    65.             return;  
    66.   
    67.         // 获取像元最大值与最小值  
    68.         double[] extremes = WWBufferUtil.computeExtremeValues(  
    69.                 raster.getBuffer(), raster.getTransparentValue());  
    70.         if (extremes == null)  
    71.             return;  
    72.   
    73.         // 创建AnalyticSurface并设置其属性  
    74.         final AnalyticSurface surface = new AnalyticSurface();  
    75.         surface.setSector(raster.getSector());  
    76.         surface.setDimensions(raster.getWidth(), raster.getHeight());  
    77.         surface.setValues(AnalyticSurface.createColorGradientValues(  
    78.                 raster.getBuffer(), raster.getTransparentValue(), extremes[0],  
    79.                 extremes[1], minHue, maxHue));  
    80.         // surface.setVerticalScale(5e3);  
    81.         // 设置表面渲染方式为 CLAMP_TO_GROUND  
    82.         surface.setAltitudeMode(WorldWind.CLAMP_TO_GROUND);  
    83.         AnalyticSurfaceAttributes attr = new AnalyticSurfaceAttributes();  
    84.         attr.setDrawOutline(false);  
    85.         attr.setDrawShadow(false);  
    86.         attr.setInteriorOpacity(0.6);  
    87.         surface.setSurfaceAttributes(attr);  
    88.   
    89.         // 设置图例样式  
    90.         Format legendLabelFormat = new DecimalFormat("# m")  
    91.         {  
    92.             public StringBuffer format(double number, StringBuffer result,  
    93.                     FieldPosition fieldPosition)  
    94.             {  
    95.                 double valueInFeet = number;  
    96.                 return super.format(valueInFeet, result, fieldPosition);  
    97.             }  
    98.         };  
    99.   
    100.         // 创建图例  
    101.         final AnalyticSurfaceLegend legend = AnalyticSurfaceLegend.fromColorGradient(  
    102.                 extremes[0], extremes[1], minHue, maxHue,  
    103.                 AnalyticSurfaceLegend.createDefaultColorGradientLabels(  
    104.                         extremes[0], extremes[1], legendLabelFormat),  
    105.                 AnalyticSurfaceLegend.createDefaultTitle("Legend"));  
    106.         legend.setOpacity(0.8);  
    107.         legend.setScreenLocation(new Point(100, 300));  
    108.   
    109.         SwingUtilities.invokeLater(new Runnable()  
    110.         {  
    111.             public void run()  
    112.             {  
    113.                 surface.setClientLayer(outLayer);  
    114.                 outLayer.addRenderable(surface);  
    115.                 outLayer.addRenderable(createLegendRenderable(surface, 600,  
    116.                         legend));  
    117.             }  
    118.         });  
    119.     }  
    120.   
    121.     /** 
    122.      *  
    123.      * @方法名称: loadRasterElevations ; 
    124.      * @方法描述: 读取数据(单波段) ; 
    125.      * @参数 :@param path 
    126.      * @参数 :@return 
    127.      * @返回类型: BufferWrapperRaster ; 
    128.      * @创建人:刘硕; 
    129.      * @创建时间:2015-1-22 上午11:25:40; 
    130.      * @throws 
    131.      */  
    132.     public static BufferWrapperRaster loadRasterElevations(String path)  
    133.     {  
    134.         // Download the data and save it in a temp file.  
    135.         File file = ExampleUtil.saveResourceToTempFile(path,  
    136.                 "." + WWIO.getSuffix(path));  
    137.   
    138.         // Create a raster reader for the file type.  
    139.         DataRasterReaderFactory readerFactory = (DataRasterReaderFactory) WorldWind.createConfigurationComponent(AVKey.DATA_RASTER_READER_FACTORY_CLASS_NAME);  
    140.         DataRasterReader reader = readerFactory.findReaderFor(file, null);  
    141.   
    142.         try  
    143.         {  
    144.             // Before reading the raster, verify that the file contains  
    145.             // elevations.  
    146.             AVList metadata = reader.readMetadata(file, null);  
    147.             if (metadata == null  
    148.                     || !AVKey.ELEVATION.equals(metadata.getStringValue(AVKey.PIXEL_FORMAT)))  
    149.             {  
    150.                 String msg = Logging.getMessage(  
    151.                         "ElevationModel.SourceNotElevations",  
    152.                         file.getAbsolutePath());  
    153.                 Logging.logger().severe(msg);  
    154.                 throw new IllegalArgumentException(msg);  
    155.             }  
    156.   
    157.             // Read the file into the raster.  
    158.             DataRaster[] rasters = reader.read(file, null);  
    159.             if (rasters == null || rasters.length == 0)  
    160.             {  
    161.                 String msg = Logging.getMessage(  
    162.                         "ElevationModel.CannotReadElevations",  
    163.                         file.getAbsolutePath());  
    164.                 Logging.logger().severe(msg);  
    165.                 throw new WWRuntimeException(msg);  
    166.             }  
    167.   
    168.             // Determine the sector covered by the elevations. This  
    169.             // information  
    170.             // is in the GeoTIFF file or auxiliary  
    171.             // files associated with the elevations file.  
    172.             Sector sector = (Sector) rasters[0].getValue(AVKey.SECTOR);  
    173.             if (sector == null)  
    174.             {  
    175.                 String msg = Logging.getMessage("DataRaster.MissingMetadata",  
    176.                         AVKey.SECTOR);  
    177.                 Logging.logger().severe(msg);  
    178.                 throw new IllegalArgumentException(msg);  
    179.             }  
    180.   
    181.             // Request a sub-raster that contains the whole file. This step  
    182.             // is  
    183.             // necessary because only sub-rasters  
    184.             // are reprojected (if necessary); primary rasters are not.  
    185.             int width = rasters[0].getWidth();  
    186.             int height = rasters[0].getHeight();  
    187.   
    188.             DataRaster subRaster = rasters[0].getSubRaster(width, height,  
    189.                     sector, rasters[0]);  
    190.   
    191.             // Verify that the sub-raster can create a ByteBuffer, then  
    192.             // create  
    193.             // one.  
    194.             if (!(subRaster instanceof BufferWrapperRaster))  
    195.             {  
    196.                 String msg = Logging.getMessage(  
    197.                         "ElevationModel.CannotCreateElevationBuffer", path);  
    198.                 Logging.logger().severe(msg);  
    199.                 throw new WWRuntimeException(msg);  
    200.             }  
    201.   
    202.             return (BufferWrapperRaster) subRaster;  
    203.         }  
    204.         catch (Exception e)  
    205.         {  
    206.             e.printStackTrace();  
    207.             return null;  
    208.         }  
    209.     }  
    210.   
    211.     /** 
    212.      *  
    213.      * @方法名称: createLegendRenderable ; 
    214.      * @方法描述: 创建图例 ; 
    215.      * @参数 :@param surface 
    216.      * @参数 :@param surfaceMinScreenSize 
    217.      * @参数 :@param legend 
    218.      * @参数 :@return 
    219.      * @返回类型: Renderable ; 
    220.      * @创建人:刘硕; 
    221.      * @创建时间:2015-1-22 上午11:26:07; 
    222.      * @throws 
    223.      */  
    224.     protected static Renderable createLegendRenderable(  
    225.             final AnalyticSurface surface, final double surfaceMinScreenSize,  
    226.             final AnalyticSurfaceLegend legend)  
    227.     {  
    228.         return new Renderable()  
    229.         {  
    230.             public void render(DrawContext dc)  
    231.             {  
    232.                 Extent extent = surface.getExtent(dc);  
    233.                 if (!extent.intersects(dc.getView().getFrustumInModelCoordinates()))  
    234.                     return;  
    235.   
    236.                 if (WWMath.computeSizeInWindowCoordinates(dc, extent) < surfaceMinScreenSize)  
    237.                     return;  
    238.   
    239.                 legend.render(dc);  
    240.             }  
    241.         };  
    242.     }  
    243.   
    244. }  

    目前还很不完善,后面有需要的话打算做一个类似于ArcGIS的分级渲染工具,对于降雨量蒸散发量等数据都可以很方便的进行渲染。
     
     
  • 相关阅读:
    以用户、组织结构和权限为例,论如何将基于关系型数据库的设计简化
    spring InitializingBean接口
    DelegatingFilterProxy
    组织机构权限系统的实现(工作流)
    activiti 引擎 数据库设计说明书
    modeler与activiti进行整合
    流程引擎的API和服务基础
    广东程序员在加利福尼亚
    开源 -- 机器学习相关报道
    国内一些大公司的开源项目
  • 原文地址:https://www.cnblogs.com/telwanggs/p/6774690.html
Copyright © 2020-2023  润新知