1. 程式人生 > >ArcGIS for Android 100.3.0(16):RasterLayer(柵格圖層)

ArcGIS for Android 100.3.0(16):RasterLayer(柵格圖層)

柵格圖層(RasterLayer)

用以載入展示移動端本地檔案、移動鑲嵌資料集、影像服務。

api地址

1.影像服務

   mMapView = (MapView) findViewById(R.id.mapView);
        ArcGISMap map = new ArcGISMap(Basemap.createDarkGrayCanvasVector());
        mMapView.setMap(map);
        // create image service raster as raster layer
        final ImageServiceRaster imageServiceRaster = new
ImageServiceRaster(image_service_url); final RasterLayer rasterLayer = new RasterLayer(imageServiceRaster); // add raster layer as map operational layer map.getOperationalLayers().add(rasterLayer); // zoom to the extent of the raster service rasterLayer.addDoneLoadingListener(new
Runnable() { @Override public void run() { if (rasterLayer.getLoadStatus() == LoadStatus.LOADED) { // get the center point Point centerPnt = imageServiceRaster.getServiceInfo().getFullExtent().getCenter(); mMapView.setViewpointCenterAsync(centerPnt, 55000000
); } } }); }

2.柵格檔案

 Raster raster = new Raster(Environment.getExternalStorageDirectory().getAbsolutePath() + "/xhk.tif");
        // create a raster layer
        final RasterLayer rasterLayer = new RasterLayer(raster);
        ArcGISMap map = new ArcGISMap(Basemap.createImagery());
        mMapView.setMap(map);
        map.getOperationalLayers().add(rasterLayer);
        // set viewpoint on the raster
        rasterLayer.addDoneLoadingListener(new Runnable() {
            @Override
            public void run() {
                mMapView.setViewpointGeometryAsync(rasterLayer.getFullExtent(), 50);
            }
        });

3.GeoPackage

 GeoPackage geoPackage = new GeoPackage(Environment.getExternalStorageDirectory() + "/ArcGIS/Samples/GeoPackage/AuroraCO.gpkg";
 geoPackage.loadAsync();
 geoPackage.addDoneLoadingListener(() -> {
            if (geoPackage.getLoadStatus() == LoadStatus.LOADED) {
                if (!geoPackage.getGeoPackageRasters().isEmpty()) {
                    // read raster images and get the first one
                    Raster geoPackageRaster = geoPackage.getGeoPackageRasters().get(0);

                    // create a layer to show the raster
                    RasterLayer geoPackageRasterLayer = new RasterLayer(geoPackageRaster);

                    // add the image as a raster layer to the map (with default symbology)
                    mMapView.getMap().getOperationalLayers().add(geoPackageRasterLayer);

                } else {
                    String emptyMessage = "No rasters found in this GeoPackage!";
                    Toast.makeText(RasterLayerGeopackageActivity.this, emptyMessage, Toast.LENGTH_LONG).show();
                    Log.e(TAG, emptyMessage);
                }
            } else {
                String error = "GeoPackage failed to load!";
                Toast.makeText(RasterLayerGeopackageActivity.this, error, Toast.LENGTH_LONG).show();
                Log.e(TAG, error);
            }
        });

4.移動鑲嵌資料集(MosaicDatasetRaster)

String rasterFilePath = "/path/to/mosaic.sqlite";
mainMapView = (MapView) findViewById(R.id.mainMapView);
 ArcGISMap mainArcGISMap = new ArcGISMap(Basemap.createTopographic());
mainMapView.setMap(mainArcGISMap);
List<String> mainMosaicDatasetRasterNames = MosaicDatasetRaster.getNames(rasterFilePath);
                for (String name: mainMosaicDatasetRasterNames
                     ) {
                    MosaicDatasetRaster mainMosaicDatasetRaster = new MosaicDatasetRaster(urlOrPath,name);
                    RasterLayer mainMDRasterLayer = new RasterLayer(mainMosaicDatasetRaster);
                    mainArcGISMap.getOperationalLayers().add(mainMDRasterLayer);
                }

5.RenderingRuleInfo(渲染規則)

用以定義如何對請求的影像進行渲染和處理。

它可以從服務中定義的名稱建立,也可以使用獲得getRenderingRuleInfos()。它可以用來構建一個RenderingRule。

通過ImageServiceRaster,獲取RenderingRuleInfo,進一步得到Rendering Rule。

下面給出官方案例:

public class RasterRenderingRuleActivity extends AppCompatActivity {

    private MapView mMapView;

    private ArcGISMap map;

    private String image_service_url = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/CharlotteLAS/ImageServer";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_raster_rendering_rule);

        mMapView = findViewById(R.id.mapView);

        map = new ArcGISMap(Basemap.createStreets());
        mMapView.setMap(map);

        // create image service raster as raster layer and add to map
        final ImageServiceRaster imageServiceRaster = new ImageServiceRaster(image_service_url);
        final RasterLayer imageRasterLayer = new RasterLayer(imageServiceRaster);
        map.getOperationalLayers().add(imageRasterLayer);

        Spinner spinner = findViewById(R.id.spinner);
        final List<String> renderRulesList = new ArrayList<>();
        final ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, renderRulesList);
        spinner.setAdapter(spinnerAdapter);
        // zoom to the extent of the raster service
        imageRasterLayer.addDoneLoadingListener(new Runnable() {
            @Override
            public void run() {
                if (imageRasterLayer.getLoadStatus() == LoadStatus.LOADED) {
                    // zoom to extent of raster
                    mMapView.setViewpointGeometryAsync(imageServiceRaster.getServiceInfo().getFullExtent());
                    // get the predefined rendering rules and add to spinner
                    List<RenderingRuleInfo> renderingRuleInfos = imageServiceRaster.getServiceInfo().getRenderingRuleInfos();
                    for (RenderingRuleInfo renderRuleInfo : renderingRuleInfos) {
                        String renderingRuleName = renderRuleInfo.getName();
                        renderRulesList.add(renderingRuleName);
                        // update array adapter with list update
                        spinnerAdapter.notifyDataSetChanged();
                    }
                }
            }
        });

        // listen to the spinner
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
                applyRenderingRule(imageServiceRaster, position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {
                Log.d("MainActivity", "Spinner nothing selected");
            }
        });

    }

    /**
     * Apply a rendering rule on a Raster and add it to the map
     *
     * @param imageServiceRaster image service raster to apply rendering on
     * @param index              spinner selected position representing the rule to apply
     */
    private void applyRenderingRule(ImageServiceRaster imageServiceRaster, int index) {
        // clear all rasters
        map.getOperationalLayers().clear();
        // get the rendering rule info at the selected index
        RenderingRuleInfo renderRuleInfo = imageServiceRaster.getServiceInfo().getRenderingRuleInfos().get(index);
        // create a rendering rule object using the rendering rule info
        RenderingRule renderingRule = new RenderingRule(renderRuleInfo);
        // create a new image service raster
        ImageServiceRaster appliedImageServiceRaster = new ImageServiceRaster(image_service_url);
        // apply the rendering rule
        appliedImageServiceRaster.setRenderingRule(renderingRule);
        // create a raster layer using the image service raster
        RasterLayer rasterLayer = new RasterLayer(appliedImageServiceRaster);
        // add the raster layer to the map
        map.getOperationalLayers().add(rasterLayer);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mMapView.pause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mMapView.resume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mMapView.dispose();
    }
}

通過Json設定渲染規則:

// create rendering rule
RenderingRule renderingRule = new RenderingRule("{\"rasterFunction\" : \"Hillshade\",\"rasterFunctionArguments\" : {\"Azimuth\" : 215.0,\"Altitude\" : 75.0,\"ZFactor\" 未完
// get a property of rendering rule
renderingRule.getRenderingRuleJson();
// set on image service raster
serviceRaster.setRenderingRule(renderingRule);
// create a raster layer
RasterLayer layer = new RasterLayer(serviceRaster);

6.RasterFunction(定義載入)

RasterFunction是針對Raster結合展現的方法進而呈現不同渲染的影像,本質上不改變源資料。

案例:

通過RasterFunction定義山體陰影,得到新的RasterLayer

/**
 * RasterFunction定義載入
 * RasterFunction是針對Raster結合展現的方法進而呈現不同渲染的影像,本質上不改變源資料。
 */
public class RasterFunctionServiceActivity extends AppCompatActivity {


    private final String TAG = MainActivity.class.getSimpleName();

    private MapView mMapView;

    private Button mRasterFunctionButton;

    private String image_service_raster_url="http://sampleserver6.arcgisonline.com/arcgis/rest/services/NLCDLandCover2001/ImageServer";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_raster_function_service);

        mMapView = findViewById(R.id.mapView);
        mRasterFunctionButton = findViewById(R.id.rasterButton);
        mRasterFunctionButton.setEnabled(false);

        // create a map with the BasemapType topographic
        ArcGISMap map = new ArcGISMap(Basemap.createDarkGrayCanvasVector());
        final ImageServiceRaster imageServiceRaster = new ImageServiceRaster(image_service_raster_url);
        final RasterLayer imageRasterLayer = new RasterLayer(imageServiceRaster);
        map.getOperationalLayers().add(imageRasterLayer);

        // zoom to the extent of the raster service
        imageRasterLayer.addDoneLoadingListener(() -> {
            if (imageRasterLayer.getLoadStatus() == LoadStatus.LOADED) {
                // get the center point
                Point centerPnt = imageServiceRaster.getServiceInfo().getFullExtent().getCenter();
                mMapView.setViewpointCenterAsync(centerPnt, 55000000);
                mRasterFunctionButton.setEnabled(true);
            } else {
                String error = "Error loading image raster layer: " + imageRasterLayer.getLoadError();
                Log.e(TAG, error);
                Toast.makeText(this, error, Toast.LENGTH_LONG).show();
            }
        });

        // 點選按鈕:通過RasterFunction定義山體陰影,得到新的RasterLayer
        mRasterFunctionButton.setOnClickListener(v -> applyRasterFunction(imageServiceRaster));

        // set the map to be displayed in this view
        mMapView.setMap(map);
    }

    private void applyRasterFunction(Raster raster) {
        // 通過Json設定渲染規則
        RasterFunction rasterFuntionFromJson = RasterFunction.fromJson(getString(R.string.hillshade_simplified));
        // get parameter name value pairs used by hillside
        RasterFunctionArguments rasterFunctionArguments = rasterFuntionFromJson.getArguments();
        // get a list of raster names associated with the raster function
        List<String> rasterNames = rasterFunctionArguments.getRasterNames();
        rasterFunctionArguments.setRaster(rasterNames.get(0), raster);
        // create raster as raster layer
        raster = new Raster(rasterFuntionFromJson);
        RasterLayer hillshadeLayer = new RasterLayer(raster);
        mMapView.getMap().getOperationalLayers().add(hillshadeLayer);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mMapView.pause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mMapView.resume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mMapView.dispose();
    }
}

json字串:

<string name="hillshade_simplified">
        {
        \"raster_function_arguments\":
        {
        \"z_factor\":{\"double\":25.0,\"type\":\"Raster_function_variable\"},
        \"slope_type\":{\"raster_slope_type\":\"none\",\"type\":\"Raster_function_variable\"},
        \"azimuth\":{\"double\":315,\"type\":\"Raster_function_variable\"},
        \"altitude\":{\"double\":45,\"type\":\"Raster_function_variable\"},
        \"type\":\"Raster_function_arguments\",
        \"raster\":{\"name\":\"raster\",\"is_raster\":true,\"type\":\"Raster_function_variable\"},
        \"nbits\":{\"int\":8,\"type\":\"Raster_function_variable\"}
        },
        \"raster_function\":{\"type\":\"Hillshade_function\"},
        \"type\":\"Raster_function_template\"
        }
    </string>

柵格渲染器(RasterRenderer)

RasterRenderer能夠對柵格圖層( RasterLayer )進行展示和視覺化。目前包括以下內容:

  1. HillshadeRenderer:山體陰影渲染
  2. BlendRenderer:混合渲染
  3. ColormapRenderer :色彩對映表渲染
  4. StretchRenderer:拉伸渲染
  5. RGBRenderer:RGB 渲染

這些渲染器官方例子中都有,有興趣的可以自己去下載,下面就來看看官方案例.

HillshadeRenderer(山體陰影渲染)

主要針對數字高程模型、單波段柵格資料,通過設定太陽的方位角和高出地平線的高度(角度或坡度),建立一個灰度級的3D高程表面。

構造方法1:

altitude:太陽高度角,預設45°
azimuth:太陽方位角,預設315°
zFactor:垂直方向的拉伸誇張程度

HillshadeRenderer(double altitude, double azimuth, double zFactor)

構造方法2:

HillshadeRenderer(double altitude, double azimuth, double zFactor, SlopeType slopeType, double pixelSizeFactor, double pixelSizePower, int outputBitDepth) 

使用:

mainMapView =(MapView) findViewById(R.id.mapView);
mainMapView.setAttributionTextVisible(false);
ArcGISMap mainArcGISMap = new ArcGISMap(new Basemap());
mainMapView.setMap(mainArcGISMap);
String rasterFilePath = getResources().getString(R.string.raster_file_path);
Raster mainRasterFile = new Raster(rasterFilePath);
mainRasterLayer = new RasterLayer(mainRasterFile);
mAltitude = 45;
mAzimuth = 315;
mZFactor = 0.000016;
mSlopeType = SlopeType.NONE;
mPixelSizeFactor = 1;
mPixelSizePower = 1;
mOutputBitDepth = 8;
HillshadeRenderer hillshadeRenderer = new HillshadeRenderer(mAltitude, mAzimuth,
        mZFactor, mSlopeType, mPixelSizeFactor, mPixelSizePower, mOutputBitDepth);
mainRasterLayer.setRasterRenderer(hillshadeRenderer);
mainArcGISMap.getOperationalLayers().add(mainRasterLayer);

BlendRenderer(混合渲染)

將一張山體陰影的影像(柵格Raster),混合入要渲染的原始柵格,讓原始柵格看起來具備地形陰影效果。

mainMapView =(MapView) findViewById(R.id.mapView);
mainMapView.setAttributionTextVisible(false);
ArcGISMap mainArcGISMap = new ArcGISMap(new Basemap());
mainMapView.setMap(mainArcGISMap);
String rasterFilePath = getResources().getString(R.string.raster_file_path);
Raster mainRasterFile = new Raster(rasterFilePath);
String rasterDEMFilePath = getResources().getString(R.string.elevation_file_path);
mainDEMRaster = new Raster(rasterDEMFilePath);
mainRasterLayer = new RasterLayer(mainRasterFile);
mAltitude = 45;
mAzimuth = 315;
mZFactor = 1.5;
mSlopeType = SlopeType.NONE;
//ColorRamp.PresetType不能設定為NONE,不然會報錯
mColorRampType = ColorRamp.PresetType.DEM_LIGHT;
mPixelSizeFactor = 1;
mPixelSizePower = 1;
mOutputBitDepth = 8;
ColorRamp colorRamp = new ColorRamp(mColorRampType, 800);
BlendRenderer blendRenderer = new BlendRenderer(
        mainDEMRaster,
        Collections.singletonList(9.0),
        Collections.singletonList(255.0),
        null,
        null,
        null,
        null,
        colorRamp,
        mAltitude,
        mAzimuth,
        mZFactor,
        mSlopeType,
        mPixelSizeFactor,
        mPixelSizePower,
        mOutputBitDepth);
mainRasterLayer.setRasterRenderer(blendRenderer);
mainArcGISMap.getOperationalLayers().add(mainRasterLayer);
mainRasterLayer.loadAsync();
mainRasterLayer.addDoneLoadingListener(new Runnable() {
    @Override
    public void run() {
        mainMapView.setViewpointGeometryAsync(mainRasterLayer.getFullExtent(), 50);
    }
});

ColormapRenderer(色彩對映表渲染)

定義使用顏色對映的渲染器。如果希望柵格圖層中的值由指定顏色表示,則可以使用此渲染器。

通過提供柵格畫素值的離散對映顏色,所有畫素匹配指定的值使用對映呈現顏色。這可以用於土地分類等任務。

  private void loadRaster() {
        // create a raster from a local raster file
        Raster raster = new Raster(buildRasterPath());
        // create a raster layer
        final RasterLayer rasterLayer = new RasterLayer(raster);
        // create a Map with imagery basemap
        ArcGISMap map = new ArcGISMap(Basemap.createImagery());
        // add the map to a map view
        mMapView.setMap(map);
        // add the raster as an operational layer
        map.getOperationalLayers().add(rasterLayer);
        // create a color map where values 0-149 are red (Color.RED) and 150-250 are yellow (Color.Yellow)
        List<Integer> colors = new ArrayList<>();
        for (int i = 0; i <= 250; i++) {
            if (i < 150) {
                colors.add(i, Color.RED);
            } else {
                colors.add(i, Color.YELLOW);
            }
        }
        // create a colormap renderer
        ColormapRenderer colormapRenderer = new ColormapRenderer(colors);
        // set the ColormapRenderer on the RasterLayer
        rasterLayer.setRasterRenderer(colormapRenderer);
        // set Viewpoint on the Raster
        rasterLayer.addDoneLoadingListener(new Runnable() {
            @Override
            public void run() {
                if (rasterLayer.getLoadStatus() == LoadStatus.LOADED) {
                    mMapView.setViewpointGeometryAsync(rasterLayer.getFullExtent(), 50);
                } else {
                    String error = "RasterLayer failed to load: " + rasterLayer.getLoadError().getMessage();
                    Log.e(TAG, error);
                    Toast.makeText(ColormapRendererActivity.this, error, Toast.LENGTH_LONG).show();
                }
            }
        });
    }

  private String buildRasterPath() {
        // get sdcard resource name
        File extStorDir = Environment.getExternalStorageDirectory();
        // get the directory
        String extSDCardDirName = "ArcGIS/samples/raster";
        // get raster filename
        String filename = "ShastaBW";
        // create the full path to the raster file
        return extStorDir.getAbsolutePath()
                + File.separator
                + extSDCardDirName
                + File.separator
                + filename
                + ".tif";
    }

StretchRenderer(拉伸渲染)

用於以平滑漸變的顏色顯示連續的柵格像元值。使用“拉伸”渲染器來繪製單波段的連續資料。該方法非常適合於諸如影像、航空像片或高程模型等要顯示的像元值位於較大範圍的柵格資料。

mainMapView = (MapView) findViewById(R.id.mapView);
mainMapView.setAttributionTextVisible(false);
ArcGISMap mainArcGISMap = new ArcGISMap(new Basemap());
mainMapView.setMap(mainArcGISMap);
String rasterFilePath = getResources().getString(R.string.raster_file_path);
Raster mainRasterFile = new Raster(rasterFilePath);
mainRasterLayer = new RasterLayer(mainRasterFile);
mMin = 0;
mMax = 255;
mPercentClipMin = 0;
mPercentClipMax = 99;
mStdDevFactor = 1;
MinMaxStretchParameters stretchParameters = new MinMaxStretchParameters(
        Collections.singletonList((double) mMin),
        Collections.singletonList((double) mMax));
PercentClipStretchParameters stretcPChParameters = new PercentClipStretchParameters(mPercentClipMin, mPercentClipMax);
StretchRenderer stretchRenderer = new StretchRenderer(stretchParameters, Collections.singletonList((double) 1.5), true, null);
mainRasterLayer.setRasterRenderer(stretchRenderer);
mainArcGISMap.getOperationalLayers().add(mainRasterLayer);
mainRasterLayer.loadAsync();
mainRasterLayer.addDoneLoadingListener(new Runnable() {
    @Override
    public void run() {
        mainMapView.setViewpointGeometryAsync(mainRasterLayer.getFullExtent(), 50);
    }
});

RGBRenderer(RGB 渲染)

RGB 渲染與拉伸渲染使用相同的方法,但前者允許以“紅、綠、藍”合成方式組合多個波段。在使用多波段柵格資料集(如衛星或航空影像)時,可以使用RGB 渲染來顯示不同的波段組合。

mainMapView = (MapView) findViewById(R.id.mapView);
mainMapView.setAttributionTextVisible(false);
ArcGISMap mainArcGISMap = new ArcGISMap(new Basemap());
mainMapView.setMap(mainArcGISMap);
String rasterFilePath = getResources().getString(R.string.raster_file_path);
Raster mainRasterFile = new Raster(rasterFilePath);
mainRasterLayer = new RasterLayer(mainRasterFile);
mMinR = 0;
mMaxR = 255;
mMinG = 0;
mMaxG = 255;
mMinB = 0;
mMaxB = 255;
mPercentClipMin = 0;
mPercentClipMax = 99;
mStdDevFactor = 1;
MinMaxStretchParameters stretchParameters = new MinMaxStretchParameters(
        Arrays.asList((double) mMinR, (double) mMinG, (double) mMinB),
        Arrays.asList((double) mMaxR, (double) mMaxG, (double) mMaxB));
RGBRenderer rgbRenderer = new RGBRenderer(stretchParameters, Arrays.asList(0, 1, 2), null, true);
mainRasterLayer.setRasterRenderer(rgbRenderer);
mainArcGISMap.getOperationalLayers().add(mainRasterLayer);
mainRasterLayer.loadAsync();
mainRasterLayer.addDoneLoadingListener(new Runnable() {
    @Override
    public void run() {
        mainMapView.setViewpointGeometryAsync(mainRasterLayer.getFullExtent(), 50);
    }
});