POST
|
I was waiting for someone to answer this....but I'm curious how this works (I haven't tried it yet), the cursor property of the tool class: http://resources.arcgis.com/en/help/main/10.2/index.html#//014p00000027000000 Cursor ID #2 is the hourglass....doesn't appear to be animated though, sorry (because that would be cool). Seems there is *almost* an example here of it in action with __init__(self): http://resources.arcgis.com/en/help/main/10.2/index.html#//014p0000001q000000 If you can't get it working, I'll take a shot at it when I get more time....but please post back if you do. I see what you mean about letting users know it is actually working and not get click-happy. Wayne EDIT: The above applies to a tool - what if it is a 'button' add-in?....apparently there's an image property but I haven't played with that either and I don't know if you can change that during runtime (probably not because these props are stored in config.xml and by runtime I imagine it is not possible to reread properties): Image (optional) This should be a 16-by-16 pixel image used to symbolize your button. The image format should be one of the commonly used formats (that is, .bmp, .jpg, and so on). The image will be copied to the Images folder created in your add-in project. http://resources.arcgis.com/en/help/main/10.2/index.html#/button/014p0000001z000000/ Then again, the button class has a 'checked' property that shows the button as if in a depressed state (false by default, which is the 'undepressed' state). http://resources.arcgis.com/en/help/main/10.2/index.html#//014p00000029000000
... View more
05-04-2014
06:10 PM
|
0
|
0
|
586
|
POST
|
Well, it depends on the type of polygon and orientation - do you mean a rectangular polygon? Minimum bounding geometry is one way, see this: http://resources.arcgis.com/en/help/main/10.2/index.html#//00170000003q000000 The graphic row for polygon shows the various geometry methods - check out RECTANGLE_BY_WIDTH, RECTANGLE_BY_AREA, and ENVELOPE. Also, there's the convex hull property 'getHullRectangle' --- gives you a space-delimited coordinate pair string of the vertices. You can use the distance formula to back out the height/width if not oriented 'orthogonally' to the x/y axes. http://resources.arcgis.com/en/help/main/10.2/index.html#//018z00000061000000 Wayne EDIT- Python has a math module with trig functions that will help too. ...specifically related to the distance formula: math.hypot(x,y) https://docs.python.org/2.7/library/math.html#trigonometric-functions
... View more
05-04-2014
05:50 PM
|
0
|
0
|
3013
|
POST
|
Very interesting - I was tripped up by GroupLayers with making a value parameter list using the ToolValidator. James code almost works, gave me an idea anyway - the think is I needed something to keep 'drilling in', so to speak...what's that called, recursion? Anyway, so I ended up doing this (below) with a list comprehension that works whether the layer is part of a group or not:
lyrList = sorted(set([os.path.basename(str(lyr)) for lyr in arcpy.mapping.ListLayers(mxd) if not lyr.isGroupLayer]))
...took some trial and error, since I'm no expert with list comprehensions, but it was sure interesting! Moreover it fixed this problem: http://forums.arcgis.com/threads/108553-Want-to-run-my-Python-script-as-a-script-tool-in-a-custom-toolbox#14 Thanks guys...for helping me track this down. Wayne
... View more
05-02-2014
07:57 PM
|
0
|
0
|
1602
|
POST
|
I duplicated your error - the cause is my ListLayers line in the ToolValidator code. Long story short, when layers are embedded within group layers, the returned names take on a 'longName' string, so I substituted this original line that works for non-grouped layers: lyrList = [str(lyr) for lyr in arcpy.mapping.ListLayers(mxd)] ...with this line that works for layers, grouped or not: lyrList = sorted(set([os.path.basename(str(lyr)) for lyr in arcpy.mapping.ListLayers(mxd) if not lyr.isGroupLayer])) Also the main script has been corrected to loop on all the layers by the 'short' name, in other words, the layer parameter (text list generated from the validator code) are unique values passed to the main scripts ListLayers function which in turn returns all layer objects (in a group layer or not) by that name to change the datasource. Here's the modified main script (also in the newly attached toolbox folder [remember to delete any other toolbox versions to avoid confusion]): # Script Name: Change_datasource # Description: This script allows you to select a specific layer # in your table of content and change the data source. # Created By: Pierre # Date: 29/04/2014 import arcpy import os # Read the parameter values: # 1: Input workspace # 2: Input layer # 3: Set new server connection # 4: Set new source dataset # mxdLocation = arcpy.GetParameterAsText(0) layer = arcpy.GetParameterAsText(1) serverConnection = arcpy.GetParameterAsText(2) newSource = arcpy.GetParameterAsText(3) newMXDname = arcpy.GetParameterAsText(4) def gdbType(connPath): connType = os.path.splitext(connPath)[1] if connType == '.sde': arcpy.AddMessage('\nsde source.') wsType = 'SDE_WORKSPACE' elif connType == '.gdb': arcpy.AddMessage('\nfile gdb source:') wsType = 'FILEGDB_WORKSPACE' else: arcpy.AddMessage('\nunhandled source type') wsType = '' return wsType arcpy.env.workspace = serverConnection if arcpy.Exists(newSource): wsType = gdbType(serverConnection) arcpy.AddMessage('the workspace for the new source is {0}\n'.format(serverConnection)) MXDdir = os.path.dirname(mxdLocation) newMXDname = os.path.join(MXDdir, newMXDname + '.mxd') mxd = arcpy.mapping.MapDocument(mxdLocation) # single-layer datasource replacement, 1st one listed from TOC. #lyr = arcpy.mapping.ListLayers(mxd, layer)[0] # multiple-layer datasource replacement... for lyr in arcpy.mapping.ListLayers(mxd, layer): if lyr.supports("DATASOURCE") and wsType != '': arcpy.AddMessage('DATASOURCE property is supported for {0}.\n'.format(lyr.longName)) lyr.replaceDataSource(serverConnection, wsType, newSource) else: arcpy.AddMessage('DATASOURCE property is either not supported or handling by this script is not provided.\n') if not os.path.exists(newMXDname): arcpy.AddMessage('Please check the layer properties for ALL layers named \'{0}\', checking the source change in your new map doc:'.format(layer)) arcpy.AddMessage('{0}.\n'.format(newMXDname)) mxd.saveACopy(newMXDname) else: arcpy.AddWarning('mxd name is not unique and will not be saved...\n') arcpy.AddMessage('The End.') Enjoy - let me know if you have any further problems....it's very interesting working with the ToolValidator class and interacting/debugging with it. -Wayne PS- Another thing I didn't mention that you may need depending on how you've named your layers in the TOC. You have the option to use a wildcard for the layer name you're searching for....for example, not that the following is practical for you to do, but you could form this valid wildcard combination: arcpy.mapping.ListLayers(mxd, 'BIOTA_*_ABORIGINAL_LAND*')
... View more
05-02-2014
07:44 PM
|
0
|
0
|
1275
|
POST
|
That means ListLayers did not find the layer by name...I'm not in the office to troubleshoot, but it appears that layer is within a group layer? So you may have to add additional code to also list those layers inside groups - to confirm, take the target layer outside the group and save the mxd, and rerun the script. Also, the for loop can be added back...once this problem is handled. If that's not the problem, then there may be something different about the way the layers listed by the Validator are being passed to the ListLayers function --- the reason why you need the ListLayers function is to get a handle on the layer object. The list within the validator class is just a text list for display purposes....so from there, the proper text chosen from the tool interface has to be passed into the main script. Question: Is the layer name in the TOC exactly the same as the input appears in the script dialog? ...looks like the text FME may be missing on the end? Not sure if that means anything.
... View more
05-01-2014
03:50 PM
|
0
|
0
|
562
|
POST
|
oops, I see I failed to attach the script file I meant to at the last post. Regardless, I think this script was due for a slight re-write, so I did the below revised script file (and it is reflected in the attached zip which I will remember to attach, to include the same script tool interface w/ validation -- with the new map doc param added). It occurred to me that maybe you're not providing the pathname to the new map document, so I made the script form the path to write the new file at the same root location as the orig mxd. Otherwise, with the behavior of my 10.2.1, it attempts to write to the current workspace (which may not be a regular 'file' directory). After I inadvertently wrote a map doc copy inside the Default.gdb, yes I said 'inside' my default workspace, I decided to override that behavior. There was no error, and ArcMap didn't seem to mind referencing a layer in the gdb from an mxd within the same gdb. Maybe that is by design, but I decided to 'fix' that with the following, and it also prints the file path you should check the mxd for your datasource update. If for some reason you don't provide a unique name, the save is simply not executed, and you get a warning message. This is made to handle only file or SDE gdb sources, just to keep this bare-bones simple, and there's no handling for feature datasets...so beware of that.
mxdLocation = arcpy.GetParameterAsText(0)
layer = arcpy.GetParameterAsText(1)
serverConnection = arcpy.GetParameterAsText(2)
newSource = arcpy.GetParameterAsText(3)
newMXDname = arcpy.GetParameterAsText(4)
def gdbType(connPath):
connType = os.path.splitext(connPath)[1]
if connType == '.sde':
arcpy.AddMessage('\nsde source.')
wsType = 'SDE_WORKSPACE'
elif connType == '.gdb':
arcpy.AddMessage('\nfile gdb source:')
wsType = 'FILEGDB_WORKSPACE'
else:
arcpy.AddMessage('\nunhandled source type')
wsType = ''
return wsType
arcpy.env.workspace = serverConnection
if arcpy.Exists(newSource):
wsType = gdbType(serverConnection)
arcpy.AddMessage('the workspace for the new source is {0}\n'.format(serverConnection))
MXDdir = os.path.dirname(mxdLocation)
newMXDname = os.path.join(MXDdir, newMXDname + '.mxd')
mxd = arcpy.mapping.MapDocument(mxdLocation)
lyr = arcpy.mapping.ListLayers(mxd, layer)[0] # single-layer datasource replacement, 1st one listed from TOC.
if lyr:
if lyr.supports("DATASOURCE") and wsType != '':
arcpy.AddMessage('DATASOURCE property is supported for this layer.\n')
lyr.replaceDataSource(serverConnection, wsType, newSource)
if not arcpy.Exists(newMXDname):
arcpy.AddMessage('Please check the {0} layer properties for the source change in your new map doc:'.format(lyr.name))
arcpy.AddMessage('{0}.\n'.format(newMXDname))
mxd.saveACopy(newMXDname)
else:
arcpy.AddWarning('mxd name is not unique and will not be saved...\n')
else:
arcpy.AddMessage('DATASOURCE property is either not supported or handling by this script is not provided.\n')
arcpy.AddMessage('The End.')
Let me know if you have questions. Test it out. If you need it to handle feature datasets, that handling can be fairly easily included, just I thought this approach was fair enough to show the interaction between the script tool interface (with modified Validator) and the main script itself. Just hope it runs successfully for you this time! It's ready to go if you will download the attached, extract the folder (probably advisable to delete the prior similarly named download to avoid confusion), and run the tool as-is. Report back with any error messages you receive... Wayne
... View more
05-01-2014
02:28 PM
|
0
|
0
|
562
|
POST
|
I see you're using a direct connect to SQL Server but you don't show anything that indicates what you've done in SQL Server to grant full privileges to the ArcGIS Server account. I'd check that and this may be obvious but I think you need a license higher than Basic. Also review the doc on the error code: 00090: <value> requires a registered database Desktop » Mapping » Publishing map services » Technical guide for map services » Prepare window messages http://resources.arcgis.com/en/help/main/10.2/index.html#//00sq000000m4000000 Wayne PS- Unless you're just testing, it's probably not a good idea to publish anything using the sa account.
... View more
04-29-2014
05:25 PM
|
0
|
0
|
972
|
POST
|
Hmmm, I apologize - that did not work as anticipated. As a kind of stopgap, I made a tiny script tool that should do what you want - just like a model, you can open it to edit it if you don't mind moving params around within a text editor (or input them at the interface in different order). This assumes you have fcs (fc1, fc2, and fc3) in each gdb, with no error trapping. I think it's pretty self-explanatory and I set up the input params on the tool to be AnyValue so that the validation is defeated (sorry ESRI)....so in this case you'd only enter the fc name (not including the path to the workspace). I'd like to take a look at the ModelBuilder solution again later...I think I have a better solution, but it's not been tested yet. See the attached - the script referenced by the tool is below, and of course anything not clear to you, let me know.
import os, sys, arcpy
# get params
folder = arcpy.GetParameterAsText(0)
fc1 = arcpy.GetParameterAsText(1)
fc2 = arcpy.GetParameterAsText(2)
fc3 = arcpy.GetParameterAsText(3)
# your 1st and 2nd stage erase outputs
output = arcpy.GetParameterAsText(4)
testout = arcpy.GetParameterAsText(5)
# list and iterate the gdbs
arcpy.env.workspace = folder
gdbs = arcpy.ListWorkspaces(workspace_type='FileGDB')
arcpy.AddMessage(str(gdbs))
for gdb in gdbs:
arcpy.env.workspace = gdb
arcpy.Erase_analysis(fc1, fc2, output)
arcpy.Erase_analysis(output, fc3, testout)
arcpy.AddMessage('completed erase for {0}'.format(gdb))
Again, sorry for the misunderstanding --- I think knowing what I know now about ModelBuilder behavior I'm going to test an embedded model for the Workspace iterator and use Collect Values to create a multivalue output parameter, then use a For iterator (or Multivalue iterator) to loop on the pathnames to execute each Erase. Not sure, but I think the internal validation will not trip up this approach. Wayne
... View more
04-24-2014
12:31 PM
|
0
|
0
|
1748
|
POST
|
Like this? http://forums.arcgis.com/threads/98415-Turn-fields-off-by-script?p=349972#post349972
... View more
04-24-2014
10:10 AM
|
0
|
0
|
2141
|
POST
|
I don't know if you're still working on this but think I found an easy solution - it occurred to me (maybe I'm wrong) that you just needed a little intervention to actually set the workspace from the iterator. I'm used to doing this via python, so I cheated a little and entered a small snippet:
import os, arcpy
workspace = arcpy.GetParameter(0)
# set output param
arcpy.env.workspace = workspace
arcpy.AddMessage('The set workspace is: {0}'.format(arcpy.env.workspace))
So with a minor modification of the basic structure of your model, I got this to run (see the attached) -- I'm getting empty output which is correct based on the 2 inputs I fed in for the Erase (I only used one erase; concept is the same). I notice you just have to be careful copying model components around - the ModelBuilder environment likes to source things sometimes in a funny way.....at the start it should be sourced to your Default gdb, otherwise it may falter in the validation cycle which kicks off before any model processes get launched. That's what you were running into before, with the "this or that doesn't exist" messages. I believe I made everything relative-pathed so that you can copy the folder to your local drive, then open the model for editing and set your own params. May have to set up some valid layer initialization to get past the internal validation, but that should be no big deal - let me know if you have any difficulty. Hope that helps. Enjoy, Wayne
... View more
04-24-2014
08:39 AM
|
0
|
0
|
1748
|
POST
|
It's not entirely clear to me what you're trying to do - are you trying to take all the layers by the same name (representing different zones) in different workspaces (same folder) and merge those features into a single feature class? If so, you could iterate the workspaces as you are doing and use Collect Values to then feed the multivalue list to the Merge tool. See this: http://resources.arcgis.com/en/help/main/10.2/index.html#/Examples_of_using_Model_Only_tools_in_ModelBuilder/00400000001m000000/ Wayne
... View more
04-23-2014
12:34 PM
|
0
|
0
|
1748
|
POST
|
Seems to be having a problem with your expression - maybe you have some null values?: CLAUSE = ('{0} = {1}'.format ("CO_FIPS", COFIPS)) If the problem is with the value of your variable COFIPS, then check that...otherwise, if for some reason your problem is with the fieldname "CO_FIPS" then you can try making sure the field exists and perhaps use the addfielddelimiters method. If the script had problems with one of the other parameters, you'd likely get a msg similar to "INVALID PARAMETERS". Wayne PS- By the way, there's a sample using the AddFieldDelimiters function here that appears to contain an error: AddFieldDelimiters (arcpy) http://resources.arcgis.com/en/help/main/10.2/index.html#//018v0000006p000000 # This appears to be in error- 'field_name' is used twice in the expression: sql_exp = """{0} = {1}""".format( arcpy.AddFieldDelimiters('c:/data', field_name), field_name) # ...should likely be 'state_value', the only unused parameter. # Also, note this would only work for numerical fields; txt fields would be: # """{0} = '{1}'""" so on and so forth... sql_exp = """{0} = {1}""".format( arcpy.AddFieldDelimiters('c:/data', field_name), state_value)
... View more
04-21-2014
05:28 AM
|
0
|
0
|
220
|
POST
|
Very well...one further note about computing geometry measurements-- "PLANAR measurements reflect the projection of geographic data onto the 2D surface (in other words, they will not take into account the curvature of the earth). GEODESIC, GREAT_ELLIPTIC, LOXODROME, and PRESERVE_SHAPE measurement types may be chosen as an alternative, if desired." http://resources.arcgis.com/en/help/main/10.2/index.html#//018z00000070000000 I used 'PLANAR' because I usually work with relatively small areas in a projected coord sys; 'GEODESIC' is the default measure type...in other words that was an optional parameter I 'forced' to PLANAR that if you left blank may give you a significantly different figure. I suspect it would have to be a large area (smaller areas should yield near equivalent results)...if you want to compare your PLANAR result with the default computation, open the model and remove that param in the code block, save and rerun the model and note the results. Go ahead and mark this thread answered if you're satisfied it's been closed to your satisfaction. -Wayne
... View more
04-19-2014
10:35 AM
|
0
|
0
|
898
|
POST
|
I've attached a zip file (Toolbox.zip) that should contain a 10.2.x toolbox (Toolbox.tbx) with a contained model (ingeniously named 'Model') - this model contains a Calculate Value tool with the corrected snippet...see further notes below. - !shape.area@squarekilometers! is for the field calculator or the Calculate Field tool... - For use with your tool, Calculate Value, the 'SHAPE@' token was used to return geometry with the da search cursor; area in your desired units was returned via the arcpy 'getArea' method. The code block:
def getArea(features):
areaTotal = sum([row[0].getArea('PLANAR', 'SQUAREKILOMETERS') for row in arcpy.da.SearchCursor(features, ['SHAPE@'])])
return "%s %s" % (areaTotal, 'Square Kilometers')
- ...and the 'expression' calling the 'getArea' function (notice the proper use of inline variable substitution, where 'myFeatures' is a model parameter [feature layer type] by that name):
getArea("%myFeatures%")
Wayne
... View more
04-19-2014
10:03 AM
|
0
|
0
|
898
|
POST
|
Hi Katie, I don't have much time but this was interesting enough that I can at least contribute this: I think your problem is you are using a method (AddLayerIdentifyPoint) that requires X, Y coordinate value input and your subroutine is called by your statement "DoIdentify(activeView, 300, 100)" which of course show static X, Y coordinates of 300, 100. But you stated you wanted to load your ID dialog window with your selected features, whatever they may be. Fortunately, you should be able to do this with the method, AddLayerIdentifyOID, if you stick with the same IIdentifyDialog interface (it has been superseded by IIdentifyDialog2). The .NET webhelp: ArcObjects Library Reference (CartoUI) IIdentifyDialog Interface http://help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/index.html#/IIdentifyDialog_Interface/00130000009s000000/ Looks like esri samples have commonly demonstrated the AddLayerIdentifyPoint method, including this C# snippet that appears to be basically the equivalent of your posted subroutine: [C#] Do Identify Snippet Performs an identify (via the Identify Dialog) on the layers in the Active View. http://help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/index.html#/Do_Identify_Snippet/00490000000n000000/ identifyDialog.AddLayerIdentifyPoint(layer, x, y); As a quick test to confirm you can 'commandeer' an ID window, I did this very short snippet in 10.0 VBA:
Sub test()
Dim pMxDoc As IMxDocument
Dim pActiveView As IActiveView
Dim pIdentifyDialog As IIdentifyDialog
Dim pIdentifyDialogProps As IIdentifyDialogProps
Dim pEnumLayer As IEnumLayer
Dim pLayer As ILayer2
Set pMxDoc = Application.Document
Set pActiveView = pMxDoc.FocusMap
Set pIdentifyDialog = New IdentifyDialog
Set pIdentifyDialogProps = pIdentifyDialog
Set pIdentifyDialog.Map = pMxDoc.FocusMap
Set pIdentifyDialog.Display = pActiveView.ScreenDisplay
pIdentifyDialog.ClearLayers
Set pEnumLayer = pIdentifyDialogProps.Layers
pEnumLayer.Reset
Set pLayer = pEnumLayer.Next
Do While Not pLayer Is Nothing
pIdentifyDialog.AddLayerIdentifyOID pLayer, 4
Set pLayer = pEnumLayer.Next
Loop
pIdentifyDialog.Show
End Sub
You should be able to pick this up from here -- notice the change in the loop (highlighted red above), which is actually looping the layers to display any layers with OBJECTID of 4 (I just picked a random one, but you can make a similar subroutine in vb.net to feed in OIDs instead of XY vals). Note that if you have a list of OIDs for a single layer to add to the dialog before moving on to the next pLayer, you can 'nest' a loop to iterate the OIDs per layer so that AddLayerIdentifyOID will effectively add each one. I didn't think of a way to pass the selected set you say you have, but it's simple enough to get access to the OIDs and pass that list. Hope that's clear... Wayne Note that this "New IdentifyDialog" window is independent of the system Identify window.
... View more
04-18-2014
03:14 PM
|
0
|
0
|
544
|
Title | Kudos | Posted |
---|---|---|
1 | 01-09-2013 07:16 AM | |
1 | 12-09-2013 08:44 AM | |
1 | 11-21-2013 07:35 AM | |
1 | 10-31-2012 08:28 AM | |
1 | 12-06-2012 07:44 AM |
Online Status |
Offline
|
Date Last Visited |
11-11-2020
02:23 AM
|