Advertisement
Guest User

Untitled

a guest
Jul 15th, 2017
562
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.13 KB | None | 0 0
  1. """
  2. Script Name: Map_Index.py
  3.  
  4. https://bitbucket.org/npeihl/mapindextool
  5.  
  6. Description: ArcGIS Tool written in Python. The Map Index Tool creates a geographic index of all ArcMap documents (MXDs) in a folder supplied by the user. For each MXD, the tool finds the largest dataframe on the Layout view and sends the extent of that dataframe to a shapefile in the folder (map_index.shp). Tested on ArcGIS Desktop version 10. Not tested and likely not working on ArcGIS Desktop versions 9.3.1 and below.
  7.  
  8. WARNING: This tool will destroy and overwrite any shapefile named map_index within the supplied folder. Please use with caution.
  9.  
  10. Author: Nicholas Peihl
  11. Email: nick.peihl@gmail.com
  12.  
  13. Last Modified: 04/20/2011
  14. """
  15. import arcpy
  16. import os, sys
  17. from datetime import datetime
  18. from time import strftime
  19.  
  20.  
  21. wp = arcpy.GetParameterAsText(0)
  22. spatialRef = arcpy.GetParameterAsText(1)
  23. fcName = "map_index.shp"
  24. scriptPath = sys.path[0]
  25. arcpy.AddMessage("Script path is %s" % scriptPath)
  26. toolDataPath = os.path.join(scriptPath, "ToolData")
  27. fcTemplate = os.path.join(toolDataPath, "map_index_template.shp")
  28.  
  29. arcpy.env.workspace = wp
  30. files = arcpy.ListFiles("*.mxd")
  31. if len(files) == 0:
  32. arcpy.AddError("No ArcMap Documents were found in this folder. Please try another folder.")
  33. else:
  34. if arcpy.Exists(os.path.join(wp, fcName)):
  35. arcpy.AddWarning("Existing Map Index shapefile found. Deleting the old index file.")
  36. arcpy.Delete_management(fcName)
  37.  
  38. arcpy.AddMessage("Creating the new Map Index shapefile")
  39. index = arcpy.CreateFeatureclass_management(wp, fcName, "POLYGON", fcTemplate,"","", spatialRef)
  40.  
  41. for mxd in files:
  42. mxd = wp + "\" + mxd
  43. arcpy.AddMessage("Opening map document %s" % mxd)
  44. mapDoc = arcpy.mapping.MapDocument(mxd)
  45. dataframes = arcpy.mapping.ListDataFrames(mapDoc)
  46. if len(dataframes) == 1:
  47. pFrame = dataframes[0]
  48. else:
  49. max = 0
  50. for frame in dataframes:
  51. size = frame.elementWidth * frame.elementHeight
  52. if size > max:
  53. pFrame = frame
  54. max = size
  55.  
  56. xmin = pFrame.extent.XMin
  57. ymin = pFrame.extent.YMin
  58. xmax = pFrame.extent.XMax
  59. ymax = pFrame.extent.YMax
  60. framespatialRef = pFrame.spatialReference
  61.  
  62. coords = [xmin,ymin],[xmax,ymin],[xmax,ymax],[xmin, ymax]
  63. point = arcpy.Point()
  64. array = arcpy.Array()
  65.  
  66. for coord in coords:
  67. point.X = coord[0]
  68. point.Y = coord[1]
  69. array.append(point)
  70.  
  71. polygon = arcpy.Polygon(array, framespatialRef)
  72.  
  73. arcpy.AddMessage("Adding the extent of %s to the index." % mxd)
  74. rows = arcpy.InsertCursor(index, spatialRef)
  75. row = rows.newRow()
  76. row.PATH = mapDoc.filePath
  77. row.TITLE = mapDoc.title
  78. row.AUTHOR = mapDoc.author
  79. row.LASTSAVED = mapDoc.dateSaved
  80. row.LASTUPDATE = datetime.strftime(datetime.now(),"%Y-%m-%d")
  81. row.SHAPE = polygon
  82. rows.insertRow(row)
  83.  
  84. del row
  85. del rows
  86.  
  87. dojo.require("esri.map");
  88.  
  89. function init() {
  90. var initialExtent = new esri.geometry.Extent({"xmin":244598,"ymin":6241389,"xmax":278995,"ymax":6264320,"spatialReference":{"wkid":102100}});
  91. var map = new esri.Map("map", {
  92. basemap: "streets",
  93. extent: initialExtent
  94. });
  95. dojo.connect(map, "onExtentChange", showExtent);
  96. }
  97.  
  98. function showExtent(extent) {
  99. var s = "";
  100. s = "XMin: "+ extent.xmin.toFixed(2) + " "
  101. +"YMin: " + extent.ymin.toFixed(2) + " "
  102. +"XMax: " + extent.xmax.toFixed(2) + " "
  103. +"YMax: " + extent.ymax.toFixed(2);
  104. dojo.byId("info").innerHTML = s;
  105. }
  106.  
  107. dojo.ready(init);
  108.  
  109. # Queries the logs to find the map extents requested for a given map service
  110.  
  111. # For output Featureclass creation
  112. print "nImporting ArcPy..."
  113. import arcpy
  114.  
  115. # Set Script arguments
  116. arcpy.env.overwriteOutput = True
  117.  
  118. # For Http calls
  119. import httplib, urllib, json
  120.  
  121. # For system tools
  122. import sys, datetime, os
  123.  
  124. # For reading passwords without echoing
  125. import getpass
  126.  
  127. #Defines the entry point into the script
  128. def main(argv=None):
  129. # Print some info
  130. print
  131. print "This tool is a sample script that queries the ArcGIS Server logs."
  132. print
  133.  
  134. # Ask for admin/publisher user name and password
  135. username = raw_input("Enter user name: ")
  136. password = getpass.getpass("Enter password: ")
  137.  
  138. # Ask for server name
  139. serverName = raw_input("Enter Server name: ")
  140. serverPort = 6080
  141.  
  142. # Ask for map service name
  143. mapService = raw_input("Enter map service name, using a forward slash / to denote a folder: ")
  144.  
  145. if mapService.endswith(".MapServer"):
  146. pass
  147. else:
  148. mapService += ".MapServer"
  149.  
  150. # Ask for output workspace
  151. outputWorkspace = raw_input("Enter output Workspace (Geodatabase location): ")
  152.  
  153. # Ask for output featureclass name
  154. outputFeatureclass = raw_input("Enter output Featureclass name: ")
  155.  
  156. # Construct REST service URL
  157. serviceURL = "/arcgis/rest/services/{0}".format( mapService.replace( ".", "/"))
  158.  
  159. # Get a token
  160. print "Requesting Token..."
  161. token = getToken(username, password, serverName, serverPort)
  162. if token == "":
  163. print "Could not generate a token with the username and password provided."
  164. return
  165.  
  166. # Get Extent detail for service
  167. print "nLooking up Service details..."
  168.  
  169. serviceURL = serviceURL + "/?Token=" + token
  170. fullExtent = getFullExtent( serverName, serverPort, serviceURL)
  171.  
  172. if not fullExtent:
  173. return
  174.  
  175. # Construct URL to query the logs
  176. logQueryURL = "/arcgis/admin/logs/query"
  177. logFilter = "{'services': ['" + mapService + "']}"
  178.  
  179. # Supply the log level, filter, token, and return format
  180. params = urllib.urlencode({'level': 'FINE', 'filter': logFilter, 'token': token, 'f': 'json'})
  181.  
  182. headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
  183.  
  184. # Connect to URL and post parameters
  185. print "Accessing Logs..."
  186. httpConn = httplib.HTTPConnection(serverName, serverPort)
  187. httpConn.request("POST", logQueryURL, params, headers)
  188.  
  189. # Read response
  190. response = httpConn.getresponse()
  191. if (response.status != 200):
  192. httpConn.close()
  193. print " Error while querying logs."
  194. return
  195. else:
  196. data = response.read()
  197.  
  198. # Check that data returned is not an error object
  199. if not assertJsonSuccess(data):
  200. print " Error returned by operation. " + data
  201. else:
  202. print " Operation completed successfully!"
  203.  
  204. # Deserialize response into Python object
  205. dataObj = json.loads(data)
  206. httpConn.close()
  207.  
  208. # Open Insert Cursor on output
  209. output = openCursor( outputWorkspace, outputFeatureclass, fullExtent[ "spatialReference"][ "wkid"])
  210.  
  211. if not output:
  212. return
  213.  
  214. # Need this variable to track number of events found for ExportMapImage call
  215. logEvents = 0
  216.  
  217. # Need Array to hold Shape
  218. shapeArray = arcpy.Array()
  219.  
  220. # Iterate over messages
  221. for item in dataObj[ "logMessages"]:
  222. eventDateTime = datetime.datetime.fromtimestamp( float( item[ "time"]) / 1000)
  223.  
  224. if item[ "message"].startswith( "Extent:"):
  225. eventScale = None # Scale
  226. eventInvScale = None # Inverse-Scale
  227. eventWidth = None # Width
  228. eventHeight = None # Height
  229.  
  230. # Cycle through message details
  231. for pair in item[ "message"].replace(" ", "").split( ";"):
  232. if pair.count( ":") == 1:
  233. key, val = pair.split( ":")
  234.  
  235. # Pick out Extent
  236. if key == "Extent" and val.count( ",") == 3:
  237. # Split into ordinate values
  238. MinX, MinY, MaxX, MaxY = val.split( ",")
  239. MinX = float( MinX)
  240. MinY = float( MinY)
  241. MaxX = float( MaxX)
  242. MaxY = float( MaxY)
  243.  
  244. # Make sure extent is within range
  245. if MinX > fullExtent[ "xmin"] and MaxX < fullExtent[ "xmax"] and MinY > fullExtent[ "ymin"] and MaxY < fullExtent[ "ymax"]:
  246. shapeArray.add( arcpy.Point( MinX, MinY))
  247. shapeArray.add( arcpy.Point( MinX, MaxY))
  248. shapeArray.add( arcpy.Point( MaxX, MaxY))
  249. shapeArray.add( arcpy.Point( MaxX, MinY))
  250. shapeArray.add( arcpy.Point( MinX, MinY))
  251.  
  252. # Pick out Size
  253. if key == "Size" and val.count( ",") == 1:
  254. eventWidth, eventHeight = val.split( ",")
  255. eventWidth = float( eventWidth)
  256. eventHeight = float( eventHeight)
  257.  
  258. # Pick out Scale
  259. if key == "Scale":
  260. eventScale = float( val)
  261. eventInvScale = 1 / eventScale
  262.  
  263. # Save if Shape created
  264. if shapeArray.count > 0:
  265. # Create new row
  266. newRow = output.newRow()
  267.  
  268. # Add Shape and Event Date
  269. newRow.setValue( "Shape", shapeArray)
  270. newRow.setValue( "EventDate", eventDateTime)
  271. newRow.setValue( "Scale", eventScale)
  272. newRow.setValue( "InvScale", eventInvScale)
  273. newRow.setValue( "Width", eventWidth)
  274. newRow.setValue( "Height", eventHeight)
  275.  
  276. output.insertRow( newRow)
  277.  
  278. # Clear out Array points
  279. shapeArray.removeAll()
  280.  
  281. logEvents += 1
  282.  
  283. print "nDone!nnTotal number of events found in logs: {0}".format( logEvents)
  284.  
  285. return
  286.  
  287. #A function to query service for Extent and Spatial Reference details
  288. def getFullExtent( serverName, serverPort, serviceURL):
  289. # Supply the return format
  290. params = urllib.urlencode({'f': 'json'})
  291.  
  292. headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
  293.  
  294. # Connect to URL and post parameters
  295. httpConn = httplib.HTTPConnection(serverName, serverPort)
  296. httpConn.request("POST", serviceURL, params, headers)
  297.  
  298. # Read response
  299. response = httpConn.getresponse()
  300. if (response.status != 200):
  301. httpConn.close()
  302. print "Error while querying Service details."
  303. return
  304. else:
  305. data = response.read()
  306.  
  307. # Check that data returned is not an error object
  308. if not assertJsonSuccess(data):
  309. print "Error returned by Service Query operation. " + data
  310.  
  311. # Deserialize response into Python object
  312. dataObj = json.loads(data)
  313. httpConn.close()
  314.  
  315. if not 'fullExtent' in dataObj:
  316. print "Unable to find Extent detail for '{0}'!".format( serviceURL)
  317. print dataObj
  318. elif not 'spatialReference' in dataObj[ 'fullExtent']:
  319. print "Unable to find Spatial Reference for '{0}'!".format( serviceURL)
  320. print "dataObj"
  321.  
  322. else:
  323. return dataObj[ 'fullExtent']
  324.  
  325. return
  326.  
  327. #A function to create new Featureclass and return an Insert Cursor, used to store Map Query Extents.
  328. def openCursor( workspace, featureclassName, srid):
  329. if not arcpy.Exists( workspace):
  330. print "Unable to find Workspace '{0}'...".format( workspace)
  331. return
  332.  
  333. print "Creating output Featureclass..."
  334. arcpy.CreateFeatureclass_management( workspace, featureclassName, "POLYGON", None, None, None, srid)
  335.  
  336. Featureclass = workspace + os.sep + featureclassName
  337.  
  338. print " Adding field(s)..."
  339. arcpy.AddField_management( Featureclass, "EventDate", "DATE", None, None, None, None, "NULLABLE", "NON_REQUIRED")
  340. arcpy.AddField_management( Featureclass, "Scale", "DOUBLE", 19, 2, None, None, "NULLABLE", "NON_REQUIRED")
  341. arcpy.AddField_management( Featureclass, "InvScale", "DOUBLE", 19, 12, None, None, "NULLABLE", "NON_REQUIRED")
  342. arcpy.AddField_management( Featureclass, "Width", "LONG", 9, None, None, None, "NULLABLE", "NON_REQUIRED")
  343. arcpy.AddField_management( Featureclass, "Height", "LONG", 9, None, None, None, "NULLABLE", "NON_REQUIRED")
  344.  
  345. print " Opening Insert Cursor..."
  346. return arcpy.InsertCursor( Featureclass)
  347.  
  348. #A function to generate a token given username, password and the adminURL.
  349. def getToken(username, password, serverName, serverPort):
  350. # Token URL is typically http://server[:port]/arcgis/admin/generateToken
  351. tokenURL = "/arcgis/admin/generateToken"
  352.  
  353. # URL-encode the token parameters
  354. params = urllib.urlencode({'username': username, 'password': password, 'client': 'requestip', 'f': 'json'})
  355.  
  356. headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
  357.  
  358. # Connect to URL and post parameters
  359. httpConn = httplib.HTTPConnection(serverName, serverPort)
  360. httpConn.request("POST", tokenURL, params, headers)
  361.  
  362. # Read response
  363. response = httpConn.getresponse()
  364. if (response.status != 200):
  365. httpConn.close()
  366. print "Error while fetching tokens from admin URL. Please check the URL and try again."
  367. return
  368. else:
  369. data = response.read()
  370. httpConn.close()
  371.  
  372. # Check that data returned is not an error object
  373. if not assertJsonSuccess(data):
  374. return
  375.  
  376. # Extract the token from it
  377. token = json.loads(data)
  378. return token['token']
  379.  
  380.  
  381. #A function that checks that the input JSON object
  382. # is not an error object.
  383. def assertJsonSuccess(data):
  384. obj = json.loads(data)
  385. if 'status' in obj and obj['status'] == "error":
  386. print "Error: JSON object returns an error. " + str(obj)
  387. return False
  388. else:
  389. return True
  390.  
  391. # Script start
  392. if __name__ == "__main__":
  393. sys.exit(main(sys.argv[1:]))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement