利用Arcpy发布地图服务,制作切片
2016-05-18 21:38
676 查看
因为工作需求,我需要把管理员上传的图片进行切片,供用户下载切片离线浏览。后台切片功能主要分为以下几个步骤:
ArcGIS版本是10.2,下面这些代码应该在10.0上无法运行。生成mxd文档时不支持栅格数据,我的图片大都是jpeg格式的,所以最终我更换了ArcGIS版本,妥协了…
这个函数的参数是“图片的位置”和“模板的位置”,然后将图片的名称提取出来作为新mxd文件的名称。
需要注意的是,直接添加jpg格式的图层在ArcGIS10.2中是允许的,但生成的mxd文档里面的图层样式是采用“拉伸(Stretched)”方式展示的,图片的样式直接成为灰色调了,而我需要的是“RGB合成(RGB Composite)”。因此我使用了这种“先创建临时栅格图层,再添加到mxd”的方式。
同样两个参数,这个函数需要mxd文档路径和ags文件路径作为参数。中间需要先生成服务定义文件(.sd)和服务定义草稿文件(.sddraft),然后对sddraft文件进行分析,若中间没有出现错误,现将其发送至服务器。然后再将sd文件,通过ags文件发送至服务器,更新服务。
这段代码最后我返回了刚刚发布的服务地址,后面将会用到。
这里主要用了
这个函数需要上一步返回的参数,就是那个以“*.MapServer”结尾的全路径。
这里的两个参数分别是要压缩的切片路径,然后是压缩后的输出路径(注意这里要以*.zip结尾,包括压缩文件名).
下载源码
1. 制作地图文档(*.mxd); 2. 发布地图文档; 3. 制作服务器缓存; 4. 生成切片; 5. 打包成zip
ArcGIS版本是10.2,下面这些代码应该在10.0上无法运行。生成mxd文档时不支持栅格数据,我的图片大都是jpeg格式的,所以最终我更换了ArcGIS版本,妥协了…
Arcpy制作地图文档
我没有找打直接生成地图文档的示例代码,因此我使用了SaveAs的方法,就是利用已有的空白文档(我称之为“模板”),加载上jpg图片后再“另存为”。这样的一个好处就是我可以直接在模板中定义地理坐标系,后面再发布为地图服务时会用到的,否则报错。# 创建map document def CreateMxd(imagepath,mxdpath): dirname=os.path.dirname(imagepath) imagename=os.path.basename(imagepath) dotindex=imagename.index('.') name=imagename[0:dotindex] new_mxd=os.path.abspath(dirname+"/"+name+".mxd") rasterLayer="raster" temp_mxd = arcpy.mapping.MapDocument(mxdpath) df=arcpy.mapping.ListDataFrames(temp_mxd,"Layers")[0] arcpy.MakeRasterLayer_management(imagepath,rasterLayer,"","","") addLayer=arcpy.mapping.Layer(rasterLayer) arcpy.mapping.AddLayer(df,addLayer,"TOP") temp_mxd.saveACopy(new_mxd) del temp_mxd return new_mxd
这个函数的参数是“图片的位置”和“模板的位置”,然后将图片的名称提取出来作为新mxd文件的名称。
需要注意的是,直接添加jpg格式的图层在ArcGIS10.2中是允许的,但生成的mxd文档里面的图层样式是采用“拉伸(Stretched)”方式展示的,图片的样式直接成为灰色调了,而我需要的是“RGB合成(RGB Composite)”。因此我使用了这种“先创建临时栅格图层,再添加到mxd”的方式。
发布地图文档
我们都知道,在ArcGIS10.1之后都是先将mxd文档转为sd文档,再进行发布的。这样做也是有好处的(听说是),不再赘述。官网文档给出两种方式发布地图,一是需要ArcGIS Server服务器名、用户名和密码方式验证登录,二是采用arcgis server连接文件ags的方式直接验证。我采用了后者,比如我的连接文件位置在“C:\Users\Administrator\AppData\Roaming\ESRI\Desktop10.2\ArcCatalog\arcgis on WIN-20150327EEH_6080 (admin).ags”。直接引用这个地址作为参数传入下面这个函数就行。# 发布服务 def PublishService(mxdpath,agspath): new_mxd = arcpy.mapping.MapDocument(mxdpath) dirname=os.path.dirname(mxdpath) mxdname=os.path.basename(mxdpath) dotindex=mxdname.index('.') servicename=mxdname[0:dotindex] sddraft = os.path.abspath(servicename + '.sddraft') sd = os.path.abspath(servicename + '.sd') if os.path.exists(sd): os.remove(sd) #创建服务定义草稿draft arcpy.CreateImageSDDraft(new_mxd, sddraft, servicename, 'ARCGIS_SERVER', agspath,False,None, "Ortho Images", "ortho images,image service") #分析草稿draft analysis = arcpy.mapping.AnalyzeForSD(sddraft) #打印分析结果 print "The following information was returned during analysis of the MXD:" for key in ('messages', 'warnings', 'errors'): print '----' + key.upper() + '---' vars = analysis[key] for ((message, code), layerlist) in vars.iteritems(): print '', message, ' (CODE %i)' % code print ' applies to:', for layer in layerlist: print layer.name, print # 发送草稿至服务器 if analysis['errors'] == {}: # Execute StageService. This creates the service definition. arcpy.StageService_server(sddraft, sd) # Execute UploadServiceDefinition. This uploads the service definition and publishes the service. arcpy.UploadServiceDefinition_server(sd, agspath) print "Service successfully published" else: print "Service could not be published because errors were found during analysis." print arcpy.GetMessages() return agspath.replace(".ags","/"+servicename+".MapServer")
同样两个参数,这个函数需要mxd文档路径和ags文件路径作为参数。中间需要先生成服务定义文件(.sd)和服务定义草稿文件(.sddraft),然后对sddraft文件进行分析,若中间没有出现错误,现将其发送至服务器。然后再将sd文件,通过ags文件发送至服务器,更新服务。
这段代码最后我返回了刚刚发布的服务地址,后面将会用到。
制作服务器缓存
注意哟,这里是定义服务器缓存,不是生成切片地方。这里是定义,下一步才是生成。就好比“打开存有《名侦探柯南》的云盘文件夹”,下一步才是“点击播放按钮”。#制作地图服务器缓存 def CreateCache(inputService,cachepath): # List of input variables for map service properties tilingSchemeType = "NEW" scalesType = "CUSTOM" numOfScales = "5"#此参数无效 scales = [500000000,250000000,125000000,64000000,32000000] dotsPerInch = "96" tileOrigin = "0 0" tileSize = "256 x 256" cacheTileFormat = "PNG8" tileCompressionQuality = "" storageFormat = "COMPACT" predefinedTilingScheme = "" try: starttime = time.clock() result = arcpy.CreateMapServerCache_server(inputService,cachepath,tilingSchemeType, scalesType, numOfScales, dotsPerInch,tileSize, predefinedTilingScheme,tileOrigin, scales,cacheTileFormat,tileCompressionQuality,storageFormat) # print messages to a file while result.status < 4: time.sleep(0.2) resultValue = result.getMessages() print "completed " + str(resultValue) except Exception, e: # If an error occurred, print line number and error message tb = sys.exc_info()[2] print "Failed at step 1 \n" "Line %i" % tb.tb_lineno print e.message print "Executed creation of Map server Cache schema "
这里主要用了
CreateMapServerCache_server这个函数,具体函数的意义这里就不再多说了,完全可以自己去查看ArcGIS文档。我是使用了自定义的方式切片,可以采用STANDARD方式切片,然后设置numOfScales的值就可以了。
生成切片
这里才是生成切片的地方,用到的是Arcpy的ManageMapServerCacheTiles_server函数,同样具体的参数还是需要自己去查官方文档。帮助文档上面说参数
waitForJobCompletion的值为“WAIT”时,可以从其他地方查到具体的切片进度,这里我还没去做,看以后的需求吧。
#生成瓦片 def CreateTiles(inputService): scales = "" numOfCachingServiceInstances = 2 updateMode = "RECREATE_ALL_TILES" areaOfInterest = "" waitForJobCompletion = "WAIT" updateExtents = "" try: result = arcpy.ManageMapServerCacheTiles_server(inputService, scales,updateMode,numOfCachingServiceInstances,areaOfInterest, updateExtents,waitForJobCompletion) #print messages to a file while result.status < 4: time.sleep(0.2) resultValue = result.getMessages() print "completed " + str(resultValue) print "Created cache tiles for given schema successfully" except Exception, e: # If an error occurred, print line number and error message tb = sys.exc_info()[2] print "Failed at step 1 \n" "Line %i" % tb.tb_lineno print e.message print "Created Map server Cache Tiles "
这个函数需要上一步返回的参数,就是那个以“*.MapServer”结尾的全路径。
压缩切片文件
将切片打包主要是为了便于用户下载,在线预览的话就不需要这一步了。下面的代码是参考了linda1000的博文,有兴趣的可以自己前去看看。这里的两个参数分别是要压缩的切片路径,然后是压缩后的输出路径(注意这里要以*.zip结尾,包括压缩文件名).
# MakeZipFile def MakeZipFile(filepath,zippath): filelist = [] #Check input ... fulldirname = os.path.abspath(filepath) fullzipfilename = os.path.abspath(zippath) print "Start to zip %s to %s ..." % (fulldirname, fullzipfilename) if not os.path.exists(fulldirname): print "Dir/File %s is not exist" % fulldirname return if os.path.isdir(fullzipfilename): tmpbasename = os.path.basename(filepath) fullzipfilename = os.path.normpath(os.path.join(fullzipfilename, tmpbasename)) #Get file(s) to zip ... if os.path.isfile(filepath): filelist.append(filepath) filepath = os.path.dirname(filepath) else: #get all file in directory for root, dirlist, files in os.walk(filepath): for filename in files: filelist.append(os.path.join(root,filename)) #Start to zip file ... destZip = zipfile.ZipFile(fullzipfilename, "w") for eachfile in filelist: destfile = eachfile[len(filepath):] print "Zip file %s..." % destfile destZip.write(eachfile, destfile) destZip.close() print "Zip folder succeed!"
调用
这段代码我是使用Java runtime直接调用的,可以使用这种方式一套流程走下来。但也有不大合适的地方,比如瓦片被删掉了,我只想生成一下切片等等,这样就不合适了。#******************************************** # 主 函 数 * #******************************************** # 程序运行所需参数: # 1.图片所在位置(filepath+filename) # 2.mxd模板位置(filepath+filename) # 3.arcgis server连接文件(ags)位置 # 4.生成切片缓存位置(out_path) # 5.生成压缩文件位置(out_path+zipname) if __name__ == '__main__': #验证路径是否正确 imagepath=sys.argv[1] mxdpath=sys.argv[2] agspath=sys.argv[3] cachepath=sys.argv[4] zippath=sys.argv[5] if not os.path.isfile(imagepath): print "图片文件不存在" sys.exit() if not os.path.isfile(mxdpath): print "mxd模板不存在" sys.exit() if not os.path.isfile(agspath): print "arcgis server连接文件不存在" sys.exit() if not os.path.isdir(cachepath): print "缓存目录不存在" sys.exit() # 创建mxd new_mxd=CreateMxd(imagepath,mxdpath) print "Finished CreateMxd" # 发布服务 inputService=PublishService(new_mxd,agspath) print "Finished PublishService" # 制作服务器缓存 CreateCache(inputService,cachepath) print "Finished CreateCache" # 生成瓦片 CreateTiles(inputService) print "Finished CreateTiles" # 压缩文件 tcachepath=os.path.abspath(cachepath+"/"+new_mxd[new_mxd.rindex("\\")+1:new_mxd.rindex(".")]) print tcachepath MakeZipFile(tcachepath,zippath) print "Finished MakeZipFile"
更新
使用过程中,发现无法使得切出更小比例尺的切片,最小的切片也是1:500000000。但当用户上传的图片过大时,切出的图片无法在视图内完整的看到全貌。这显然不合理,最后终于找到了解决方法。草稿文件上传至服务器前对其进行修改,sddraft文件是指上是一个符号xml标准的文件。使用python直接可以进行操作,将里面的minScale改为更大#修改草稿draft # read sddraft xml doc = DOM.parse(sddraft) # turn on caching in the configuration properties configProps = doc.getElementsByTagName('ConfigurationProperties')[0] propArray = configProps.firstChild propSets = propArray.childNodes for propSet in propSets: keyValues = propSet.childNodes for keyValue in keyValues: if keyValue.tagName == 'Key': if keyValue.firstChild.data == "minScale": # turn on caching keyValue.nextSibling.firstChild.data = "32000000000" # output to a new sddraft if os.path.exists(sddraft): os.remove(sddraft) f = open(sddraft, 'w') doc.writexml( f ) f.close()
下载源码
相关文章推荐
- Andriod arcgis保存Mapview为图片的实例代码
- 基于Arcgis for javascript实现百度地图ABCD marker的效果
- Python切片知识解析
- 理解Golang中的数组(array)、切片(slice)和map
- 深入解析Go语言编程中slice切片结构
- Python切片用法实例教程
- Python字符串切片操作知识详解
- python 切片和range()用法说明
- 在arcgis使用python脚本进行字段计算时是如何解决中文问题的
- ArcGis Map 中操作备忘
- ArcGis 的教程和资源
- 基于ArcEngine+C#开发的空间数据管理平台架构设计及功能说明
- 关于 ArcGIS 32位及64位版本问题
- 使用ArcPy对栅格数据进行批量投影坐标转换
- Python字符串切片操作知识详解
- 怎样在 C++ 中实现 Python 的切片
- Zoom to Selected Globe Features
- Python 2.5.1 切片
- 在ArcGIS中如何删除重复的点要素
- Arcgis Flex Api自定义点样式实现风场显示