自己写一个读取Arcgis Server切片的后台服务

编程入门 行业动态 更新时间:2024-10-08 10:59:56

自己写一个读取Arcgis Server<a href=https://www.elefans.com/category/jswz/34/1769942.html style=切片的后台服务"/>

自己写一个读取Arcgis Server切片的后台服务

概述:

Arcgis Server的切片得要有Arcgis Server的支持才能使用,这样就显得比较麻烦,如果对于已经切好的切片怎么样通过自己写的程序来调用展示呢,本文讲解的内容就是这些。


Arcgis 切片简介:

Arcgis Server的切片分为两种:松散型和紧凑型。松散型,就是以单个的jpg或者png文件形式存储;紧凑型,是将多个切片文件制作成一组bundle和bundlx文件,其中bundlx存储的是切片的索引,bundle存储的是切片本身。在10的版本之前,Arcgis只支持松散型的切片方式,紧凑型是在Arcgis10的版本之后才出现的。


实现方式:

1、后台读取

后台写了一个比较简单的servlet来实现切片的读取,其中实现参考了下两篇文章中的内容,最终的实现代码如下:

package com.lzugis.servlet;import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apachemons.codec.binary.Base64;import com.lzugis.tile.helper.CommonConfig;/*** Servlet implementation class TileServlet*/
@WebServlet(description = "get arcgis offline tile", urlPatterns =  {"/agstile"})
public class AgsOffTilesServiceServlet extends HttpServlet {private static final long serialVersionUID = 1L;private String rootPath = "";private static String base64Blank = "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NkZFQUUzNjgyRjJBMTFFNEFBQ0JGMEMyRjFFNUE0MUYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NkZFQUUzNjkyRjJBMTFFNEFBQ0JGMEMyRjFFNUE0MUYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2RkVBRTM2NjJGMkExMUU0QUFDQkYwQzJGMUU1QTQxRiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo2RkVBRTM2NzJGMkExMUU0QUFDQkYwQzJGMUU1QTQxRiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pij7ZYAAAAJdSURBVHja7NQxAQAACMMwwL/nYQAHJBJ6tJMU8NNIAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAGAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAYABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAEABgAYAGAAgAGAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAQAGABgAYACAAYABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAAYAGABgAIABAJcVYADnygT9CIf4ngAAAABJRU5ErkJggg==";/*** @see HttpServlet#HttpServlet()*/public AgsOffTilesServiceServlet() {super();// TODO Auto-generated constructor stubtry{//切片存储路径rootPath = CommonConfig.getVal("tile.agspath")+File.separator;}catch(Exception e){e.printStackTrace();}}/*** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)*/protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubthis.doPost(request, response);}/*** @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)*/@SuppressWarnings("resource")protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String x= request.getParameter("x");String y= request.getParameter("y");String z= request.getParameter("z");String layer= request.getParameter("layer");String type= request.getParameter("type");//file为紧凑型,image为松散型String tilePath = rootPath+layer+"/Layers/_alllayers";int level = Integer.parseInt(z);int row = Integer.parseInt(x);int col = Integer.parseInt(y);try {OutputStream os = response.getOutputStream();byte[] output = null;int outlength = 0;if(type.equals("file")){//紧凑型String l = "L" + getZero(2,z.length()) + level;int rGroup = 128 * (row / 128);String rTail = Integer.toHexString(rGroup);String r = "R" + getZero(4,rTail.length()) +rTail ;int cGroup = 128 * (col / 128);String cTail = Integer.toHexString(cGroup);String c = "C" + getZero(4,cTail.length()) + cTail;String bundleBase = String.format("%s/%s/%s%s", tilePath, l, r, c);String bundleFileName = bundleBase + ".bundle";String bundlxFileName = bundleBase + ".bundlx";File file = new File(bundleFileName);if(file.exists()){int index = 128 * (col - cGroup) + (row - rGroup);FileInputStream isBundlx = new FileInputStream(bundlxFileName);isBundlx.skip(16 + 5 * index);byte[] buffer = new byte[5];isBundlx.read(buffer);long offset = (long)(buffer[0]&0xff) + (long)(buffer[1]&0xff)*256 + (long)(buffer[2]&0xff)*65536 + (long)(buffer[3]&0xff)*16777216+ (long)(buffer[4]&0xff)*4294967296L;FileInputStream isBundle = new FileInputStream(bundleFileName);isBundle.skip(offset);byte[] lengthBytes = new byte[4];isBundle.read(lengthBytes);int length = (int)(lengthBytes[0]&0xff)+ (int)(lengthBytes[1]&0xff)*256	+ (int)(lengthBytes[2]&0xff)*65536+ (int)(lengthBytes[3]&0xff)*16777216;byte [] result = new byte[length];isBundle.read(result);if(result.length>0){output = result;outlength = length;}}else{byte[] blankImg = Base64.decodeBase64(base64Blank);InputStream is = new ByteArrayInputStream(blankImg); int count=0;while ((count = is.read(blankImg)) != -1) {output = blankImg;outlength = count;}}}else{//松散型String l = "L" + getZero(2,z.length()) + level;String strRow = Integer.toHexString(row);        String r = "R" +getZero(8,strRow.length())+ strRow;String strCol = Integer.toHexString(col);String c = "C"+getZero(8,strCol.length()) + strCol;String imgfile = tilePath+l+"/"+r+"/"+c+".png";InputStream is = null;File file = new File(imgfile);if(!file.exists()){imgfile = tilePath+l+"/"+r+"/"+c+".jpg";file = new File(imgfile);if(!file.exists()){byte[] blankImg = Base64.decodeBase64(base64Blank);is=new ByteArrayInputStream(blankImg); }else{is = new FileInputStream(imgfile);}} else{is = new FileInputStream(imgfile);}int count = 0;byte[] buffer = new byte[1024 * 1024];while ((count = is.read(buffer)) != -1) {output = buffer;outlength = count;}}os.write(output, 0, outlength);os.flush();os.close();}catch (IOException e) {e.printStackTrace();}}private String getZero(int length,int strLength){int zeroLength = length-strLength;String strZero = "";for(int i=0;i<zeroLength;i++){strZero+="0";}return strZero;}
}
2、前台调用(Openlayers2)

为方便调用展示,扩展了一个Openlayers的图层类,代码如下:

OpenLayers.Layer.AgsTileLayer = OpenLayers.Class(OpenLayers.Layer.XYZ, {url: null,tileOrigin: null,tileSize: new OpenLayers.Size(256, 256),type: 'png',useScales: false,overrideDPI: false,useArcgisServer:false,cachetype:"file",//file为紧凑型,image为松散型initialize: function(name, url, options) { OpenLayers.Layer.XYZ.prototype.initialize.apply(this, arguments);},getURL: function (bounds) {var res = this.getResolution();var originTileX = (this.tileOrigin.lon + (res * this.tileSize.w/2));var originTileY = (this.tileOrigin.lat - (res * this.tileSize.h/2));var center = bounds.getCenterLonLat();var y = (Math.round(Math.abs((center.lon - originTileX) / (res * this.tileSize.w))));var x = (Math.round(Math.abs((originTileY - center.lat) / (res * this.tileSize.h))));var z = this.map.getZoom();var url = this.url;var s = '' + x + y + z;if (OpenLayers.Util.isArray(url)) {url = this.selectUrl(s, url);}url = url + '?layer=${layer}&type=${type}&x=${x}&y=${y}&z=${z}';url = OpenLayers.String.format(url, {'layer': this.name,'type': this.cachetype,'x': x, 'y': y, 'z': z});return OpenLayers.Util.urlAppend(url, OpenLayers.Util.getParameterString(this.params));},CLASS_NAME: 'OpenLayers.Layer.AgsTileLayer'
}); 
前台页面中的调用代码如下:

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><title>openlayers map</title><link rel="stylesheet" href="../../../plugin/OpenLayers-2.13.1/theme/default/style.css" type="text/css"><style>html, body,#map{padding:0;margin:0;height:100%;width: 100%;overflow: hidden;}</style><script src="../../../plugin/OpenLayers-2.13.1/OpenLayers.js"></script><script src="../../../plugin/jquery/jquery-1.8.3.js"></script><script src="extend/AgsOffTileLayer.js"></script><script>var map;var tiled;$(window).load(function() {var bounds = new OpenLayers.Bounds(73.45100463562233, 18.16324718764174,134.97679764650596, 53.531943152223576);var options = {controls: [],maxExtent: bounds,maxResolution: 0.2403351289487642,projection: "EPSG:4326",units: 'degrees'};map = new OpenLayers.Map('map', options);OpenLayers.INCHES_PER_UNIT["千米"] = OpenLayers.INCHES_PER_UNIT["km"];OpenLayers.INCHES_PER_UNIT["米"] = OpenLayers.INCHES_PER_UNIT["m"];OpenLayers.INCHES_PER_UNIT["英里"] = OpenLayers.INCHES_PER_UNIT["mi"];OpenLayers.INCHES_PER_UNIT["英寸"] = OpenLayers.INCHES_PER_UNIT["ft"];//比例尺map.addControl(new OpenLayers.Control.ScaleLine({topOutUnits:"米",topOutUnits:"千米"}));$(".olControlScaleLineBottom").hide();map.addControl(new OpenLayers.Control.Zoom());map.addControl(new OpenLayers.Control.Navigation());tiled = new OpenLayers.Layer.AgsTileLayer( "chinashp","http://localhost:8081/tile/agstile", {isBaseLayer: true,tileSize: new OpenLayers.Size(256, 256),resolutions: [0.15228550437313793,0.07614275218656896,0.03807137609328448,0.01903568804664224,0.00951784402332112,0.00475892201166056,0.00237946100583028],tileOrigin: new OpenLayers.LonLat(-400 , 400),maxExtent: bounds,projection: 'EPSG:4326'});map.addLayers([tiled]);map.zoomToExtent(bounds);});</script>
</head>
<body>
<div id="map" style="width: 100%;"></div>
</body>
</html>`

注意:在前台页面调用的时候,有两个参数:分辨率组(resolutions)和切片原点(tileOrigin)。这两个参数是从服务的配置中获取的,你可以从服务配置文件Conf.xml中读取,Conf.xml文件位于“切片路径\Layers\”文件夹下,内容如下:

<?xml version="1.0" encoding="utf-8"?><CacheInfo xmlns:xsi="" xmlns:xs="" xmlns:typens=".1" xsi:type="typens:CacheInfo"><TileCacheInfo xsi:type="typens:TileCacheInfo"><SpatialReference xsi:type="typens:GeographicCoordinateSystem"><WKT>GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433],AUTHORITY["EPSG",4326]]</WKT><XOrigin>-400</XOrigin><YOrigin>-400</YOrigin><XYScale>11258999068426.24</XYScale><ZOrigin>-100000</ZOrigin><ZScale>10000</ZScale><MOrigin>-100000</MOrigin><MScale>10000</MScale><XYTolerance>8.983152841195215e-009</XYTolerance><ZTolerance>0.001</ZTolerance><MTolerance>0.001</MTolerance><HighPrecision>true</HighPrecision><LeftLongitude>-180</LeftLongitude><WKID>4326</WKID><LatestWKID>4326</LatestWKID></SpatialReference><TileOrigin xsi:type="typens:PointN"><X>-400</X><Y>399.99999999999977</Y></TileOrigin><TileCols>256</TileCols><TileRows>256</TileRows><DPI>96</DPI><PreciseDPI>96</PreciseDPI><LODInfos xsi:type="typens:ArrayOfLODInfo"><LODInfo xsi:type="typens:LODInfo"><LevelID>0</LevelID><Scale>64000000</Scale><Resolution>0.15228550437313793</Resolution></LODInfo><LODInfo xsi:type="typens:LODInfo"><LevelID>1</LevelID><Scale>32000000</Scale><Resolution>0.076142752186568963</Resolution></LODInfo><LODInfo xsi:type="typens:LODInfo"><LevelID>2</LevelID><Scale>16000000</Scale><Resolution>0.038071376093284481</Resolution></LODInfo><LODInfo xsi:type="typens:LODInfo"><LevelID>3</LevelID><Scale>8000000</Scale><Resolution>0.019035688046642241</Resolution></LODInfo><LODInfo xsi:type="typens:LODInfo"><LevelID>4</LevelID><Scale>4000000</Scale><Resolution>0.0095178440233211203</Resolution></LODInfo><LODInfo xsi:type="typens:LODInfo"><LevelID>5</LevelID><Scale>2000000</Scale><Resolution>0.0047589220116605602</Resolution></LODInfo><LODInfo xsi:type="typens:LODInfo"><LevelID>6</LevelID><Scale>1000000</Scale><Resolution>0.0023794610058302801</Resolution></LODInfo></LODInfos></TileCacheInfo><TileImageInfo xsi:type="typens:TileImageInfo"><CacheTileFormat>PNG</CacheTileFormat><CompressionQuality>0</CompressionQuality><Antialiasing>false</Antialiasing></TileImageInfo><CacheStorageInfo xsi:type="typens:CacheStorageInfo"><StorageFormat>esriMapCacheStorageModeCompact</StorageFormat><PacketSize>128</PacketSize></CacheStorageInfo>
</CacheInfo>

实现效果:


参考文献:

.html



传播GIS知识 | 交流GIS经验 | 分享GIS价值 | 专注GIS发展

技术博客

.NET/gisshixisheng

在线教程


Github

/

联系方式

q       q:1004740957

e-mail:niujp08@qq

公众号:lzugis15

Q Q 群:452117357(webgis)
             337469080(Android)


更多推荐

自己写一个读取Arcgis Server切片的后台服务

本文发布于:2024-02-13 15:43:42,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1759200.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:切片   后台   Arcgis   Server

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!