|
POST
|
The good news is you've encapsulated the "add a vertex at a given distance to an existing line" code to a nice, easy to use function. You can use that in another function, maybe something like this: def densify(shp, vertex_count):
# Add 1 so the final vertex isn't coincident with the line end
stride = shp.length / (vertex_count + 1)
dist = 0.0
for _ in range(vertex_count):
dist += stride
shp = insertV(dist, shp)
return shp As an aside, I misread your function as an attempt to clip off the first portion of a line, so here's some code that does that at a bonus: def shortenLineReverse(dist, shp):
newP = shp.positionAlongLine(dist).firstPoint
arr = arcpy.Array()
arr.add(newP)
part = shp.getPart(0)
for i in range(len(part)):
p = part.getObject(i)
l = shp.measureOnLine(p)
if l > dist:
arr.add(p)
return arcpy.Polyline(arr, shp.spatialReference)
... View more
06-27-2022
10:30 AM
|
0
|
0
|
3911
|
|
POST
|
You're on the right track, all arcpy Geometry objects have a JSON property, so your line #10 should be: geom_loads = json.loads(geom.JSON) For simpler jobs you can skip JSON fiddling and use some of the properties and methods on the Geometry objects themselves, such as getPart and spatialReference. For example, here's a line of code that creates a new Polyline object from the last 2 points of another Polyline: new_geom = arcpy.Polyline(geom.getPart(-1)[0][-2:], geom.spatialReference) I highly recommend you keep the official docs on hand, there's a surprising amount of built-in methods on these objects so you can build up your own little GIS factory. Here's some key links: Geometry (this is the base class for all the other Geometry types). PointGeometry Polyline Polygon Point (this is the simple 2D/3D/4D point object that all of the other Geometries are built out of. If you want the object that you deal with from a point feature class' shape field, you want "PointGeometry"). Array (this is like a Python list but is different somehow, Polyline and Polygon objects use this class to hold the Point objects they're built from. You can use standard Python index and slice syntax to extract data).
... View more
06-24-2022
10:16 AM
|
1
|
3
|
3935
|
|
POST
|
For manual vertex fiddling a good method is to extract the geometry object for each feature like with arcpy.da.UpdateCursor(my_features, "SHAPE@") as update:
for row in update:
geom = row[0] and then dump the geometry data to JSON by combining the loads function from the standard Python json library with the geometry object's JSON property. Once you're done manipulating the dictionary you get back you can use something like new_geom = arcpy.AsShape(json_data) and throw that into your update cursor. You'll probably need a few helper functions to deal with subsets of the JSON structure so you can deserialize individual points/segments as geometry objects without losing your spatial reference info. As for your specific case, if you just need to add vertices to the lines, you can find the final two vertices in the line, construct a temporary line object from that, then call the line's positionAlongLine method with use_percentage=True to dump out new vertices that won't distort your original feature. No guarantee this'll work for complex segments but it's a starting point. Have fun!
... View more
06-23-2022
04:28 PM
|
0
|
1
|
3950
|
|
IDEA
|
This is a great idea, a "retain last entry" checkbox when you configure a field in the Field Maps app* would help with a lot of focused workflows. *the online/portal Field Maps configuration app needs a mild rebrand to avoid confusion but that's a tale for another time
... View more
06-17-2022
03:48 PM
|
0
|
0
|
2633
|
|
IDEA
|
Conda supports this already, open the "Python Command Prompt" from your start menu and use this command: conda install "\path\to\my\downloaded\package.tar.bz2" I guess an "install package from path" button would be a nice feature for Pro to supplement this.
... View more
06-17-2022
08:34 AM
|
0
|
0
|
3256
|
|
IDEA
|
The Rematch Addresses pane has a variety of options and state (layer to rematch, fields for current match, fields for potential matches, locator, current feature out of available selection) that are not saved to the project file. In the event that a user has to close and then re-open the project the rematch pane has to be opened for the layer and all of these settings must be reconfigured. Serializing this information into the project file would save time for rematch workflows and could potentially lead to some sort of reusable configuration file in a later release.
... View more
06-09-2022
03:14 PM
|
0
|
0
|
869
|
|
IDEA
|
Our team has received requests from multiple clients for this functionality, would love to see it in an upcoming release.
... View more
05-25-2022
11:26 AM
|
0
|
0
|
3578
|
|
IDEA
|
Our team was able to work around this after switching from standalone servers to Enterprise but our client has now tripled the amount of requests they make as they can't cache tokens between multiple requests. I think a reasonable compromise would be to keep the 2 week limit for Portal tokens, but allow the server tokens used for direct service access to have longer expiration times. This maintains some backwards compatibility with older server setups while keeping the current level of security intact for the newer Portal workflows.
... View more
05-25-2022
11:21 AM
|
0
|
0
|
1819
|
|
IDEA
|
Add a parameter type for script tools that behaves identically to the "String" parameter, but the control is a text box that supports tabs, line breaks etc. The formatting within the text box would be carried over to the parameter value. A filter on the parameter to let the user choose syntax highlighting options (Python, text, HTML etc.) and line number display would be nice but not required. This idea came from a recent project where I wanted the user to enter arbitrary Python code into a parameter. I currently have to hack together a solution with a multivalue String parameter and convert the values into a single item. This leads to a poor UX and many formatting limitations. A Text Box input type would be a perfect fix for this as well as other script tool workflows that require large volumes of structured text from the user (large text field entries, injecting HTML formatting into fields, feeding custom query expressions into third-party web services etc.).
... View more
05-20-2022
04:44 PM
|
7
|
3
|
2758
|
|
IDEA
|
Also, forgot to mention this, but the way you use the tool is to write a Python function that takes in 1 or more fields for each record and returns a boolean value to determine if it's selected or not. For example, if you have a text field called "CustomerName" and you want to select every record whose customer has a first name over 10 characters, your python function would be "return len(customername.split()[0] if customername else 0) > 10".
... View more
05-20-2022
04:30 PM
|
0
|
0
|
19280
|
|
IDEA
|
Felt like solving a challenge so here's a working tool. I can't attach the full tool so here's the components: Parameters: Execution: import arcpy
import ast
def parseSelectionType(s):
return s.strip().upper().replace(" ", "_")
def checkFunc(funcText):
try:
ast.parse(funcText)
return True, None
except SyntaxError as e:
return False, "Invalid syntax in Python function, line {}".format(e.lineno - 1)
def buildFuncText(funcBody, fieldNames):
FUNC_NAME = "_select_func"
signature = "def {}(".format(FUNC_NAME)
if len(fieldNames):
signature += ", ".join(f.lower() for f in fieldNames)
signature += "):\n\t"
indentFuncBody = funcBody.replace("\r\n", "\n").replace("\n","\n\t")
return signature + indentFuncBody, FUNC_NAME
def main(layer, fieldNames, funcBody, selectionType="NEW_SELECTION", isInvertSelection=False):
selectFuncText, selectFuncName = buildFuncText(funcBody, fieldNames)
isValid, error = checkFunc(selectFuncText)
if not isValid:
arcpy.AddError(error)
raise SystemExit(1)
namespace = {}
exec(selectFuncText, namespace)
selectFunc = namespace[selectFuncName]
desc = arcpy.da.Describe(layer)
oidFieldName = desc["OIDFieldName"]
isOIDInFunc = True
if oidFieldName not in fieldNames:
fieldNames = ["OID@"] + fieldNames
isOIDInFunc = False
shapeFieldName = desc["shapeFieldName"]
if shapeFieldName in fieldNames:
fieldNames = [f if f != shapeFieldName else "SHAPE@" for f in fieldNames]
selectOIDs = []
with arcpy.da.SearchCursor(layer, fieldNames) as search:
for row in search:
oid = row[0]
params = row if isOIDInFunc else row[1:]
if selectFunc(*params):
selectOIDs.append(oid)
sql = "{} IN ({})".format(oidFieldName, ",".join(str(o) for o in selectOIDs))
arcpy.management.SelectLayerByAttribute(layer, selectionType, sql, isInvertSelection)
if __name__ == "__main__":
layer = arcpy.GetParameterAsText(0)
selectionType = parseSelectionType(arcpy.GetParameterAsText(1)) if arcpy.GetParameterAsText(1) else "NEW_SELECTION"
fields = [f.value for f in arcpy.GetParameter(2)]
funcBody = "\n".join(s for s in arcpy.GetParameter(3))
isInvertSelection = arcpy.GetParameter(4)
main(layer, fields, funcBody, selectionType="NEW_SELECTION", isInvertSelection=False) Validation: import ast
def checkFunc(funcText):
try:
ast.parse(funcText)
return True, None
except SyntaxError as e:
return False, "Invalid syntax in Python function, line {}".format(e.lineno - 1)
def buildFuncText(funcBody, fieldNames):
FUNC_NAME = "_select_func"
signature = "def {}(".format(FUNC_NAME)
if len(fieldNames):
signature += ", ".join(f.lower() for f in fieldNames)
signature += "):\n\t"
indentFuncBody = funcBody.replace("\r\n", "\n").replace("\n","\n\t")
return signature + indentFuncBody, FUNC_NAME
class ToolValidator:
# Class to add custom behavior and properties to the tool and tool parameters.
def __init__(self):
# set self.params for use in other function
self.params = arcpy.GetParameterInfo()
def initializeParameters(self):
# Customize parameter properties.
# This gets called when the tool is opened.
return
def updateParameters(self):
# Modify parameter values and properties.
# This gets called each time a parameter is modified, before
# standard validation.
return
def updateMessages(self):
# Customize messages for the parameters.
# This gets called after standard validation.
fields = self.params[2]
funcBody = self.params[3]
if fields.value and funcBody.value:
fieldNames = [f.value for f in fields.values]
funcBodyText = "\n".join(funcBody.values)
funcText = buildFuncText(funcBodyText, fieldNames)[0]
isValid, error = checkFunc(funcText)
if not isValid:
funcBody.setErrorMessage(error)
return
# def isLicensed(self):
# # set tool isLicensed.
# return True The Python Function Body parameter is a bit of a hack, it uses multiple string params in lieu of a proper text box (ESRI pls). I also didn't implement parameter parsing like the Calculate Field tool does so your function parameters are just the field names in lower case (e.g. the field "ParcelID" is accessed as "parcelid"). It'll also convert the shape field to python geometry objects just like the "SHAPE@" cursor token so you can do shape.firstPoint.X and such. There's probably some bugs lurking in here and using eval to run arbitrary input can cause issues but overall this'll get you what you need.
... View more
05-20-2022
03:21 PM
|
0
|
0
|
19287
|
|
IDEA
|
Allow the Destination table in a relationship class to be a registered database view. The relationship wouldn't support any features that a view would prohibit (no composite relationships, no message passing etc.) but could be used to link database view records to a parent feature or record in apps such as Field Maps. The main use of this feature in my organization would be to create a view of an entire archive table or branch versioned table in the EGDB, register that view, then allow users to jump to a list of archived records directly from a feature in various apps. To my knowledge there is no consistent method of relating data in ArcGIS without a relationship class in the database and this seems more pragmatic than defining a new relationship type at the Server/AGOL/Enterprise level.
... View more
10-28-2021
12:02 PM
|
13
|
3
|
2132
|
|
IDEA
|
When a user changes which layers are visible/non-visible in a map, there should be an app-level setting to either save this selection for the next time the map is opened or reset to the map defaults every time (i.e. the current behavior). This data would be saved only to the device, much like the feature to return to last session's extent in Web Appbuilder. This data would ideally persist unless an irreconcilable change is made to the map's layer set but having it reset on every map update isn't a deal breaker. Our organization has many maps with over a dozen layers by necessity and the default layer visibility isn't ideal for all workloads. This would be infinitely less work than creating and maintaining duplicate maps with different layers visible by default and would save our field crews time as well.
... View more
10-27-2021
04:00 PM
|
23
|
7
|
3514
|
|
POST
|
Hi Shana, My team finally has Pro 2.5.1 and I can confidently say that this issue hasn't been fixed. All geocodes were performed using the World Geocoding Service.
... View more
06-24-2020
10:33 AM
|
0
|
1
|
3835
|
|
IDEA
|
The "Authentication Required" prompt for secured layers in Collector maps is very clear and easy to read in the iOS version of Collector but is much harder to read in the Android version. Several users I support use Samsung devices for field collection and the prompt that appears in this version of Collector has barely legible username and password text fields. Many of these users can't see these fields which leads to hours of lost time troubleshooting the issue. Oddly enough the rest of the prompt is correctly using white fonts on black, including the non-placeholder username and password entries. At the very least I'd like to see the styles for this prompt updated to make the fields legible. Ideally I'd like to see the secured layers workflow on Android altered to match the workflow on iOS as this has proved to be less confusing for our users, but the former would be a quick fix.
... View more
06-04-2020
09:44 AM
|
1
|
0
|
1669
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | a week ago | |
| 1 | a week ago | |
| 2 | 2 weeks ago | |
| 1 | 2 weeks ago | |
| 1 | a month ago |
| Online Status |
Offline
|
| Date Last Visited |
8 hours ago
|