|
IDEA
|
That would be helpful. Also, do the same for $datastore and for the labeling profile. Though my guess is that evaluating this expression for each feature shown in the map each time the map is updated is going to be very slow. But for small datasets this would be great. In the meantime, you can add a field to your FC and calculate it with your expression. This works for more or less static data, but is too much of a hassle for regularily updated datasets.
... View more
02-08-2022
01:13 AM
|
0
|
0
|
3398
|
|
POST
|
It is possible. But you dont define the rule on the feature class, you do it on the work history table. // Attribute Rule on the work history table
// Triggers: Update
// Field: empty
// do nothing if meter id did not change (so you don't send senseless update requests)
if($originalfeature.MeterID == $feature.MeterID) { return null }
// get the water meter
var water_meter = First(FeatureSetByRelationshipName($feature, "RelationshipName"))
if(water_meter == null) { return null }
// Send a request to update the MeterID in the parent FC
return {
"edit": [
{
"className": "WaterMeterFC",
"updates": [
{"globalID": water_meter.GlobalID, "attributes": {"MeterID": $feature.MeterID}}
]
}
]
}
... View more
02-08-2022
12:59 AM
|
1
|
0
|
6438
|
|
POST
|
The keywords "adds", "updates", and "deletes" require an array of dictionaries. The exact requirements for each keyword can be found here: Attribute rule dictionary keywords—ArcGIS Pro | Documentation "deletes" just requires the globalID/objectID identifying the records that should be deleted: return {
"result": result,
"edit": [
{
"className": "OtherTable",
"deletes": [
{"globalID": GlobalID1},
{"globalID": GlobalID2},
{"globalID": GlobalID3},
]
}
]
} You already know how to load and filter the related features, so you just have to put it all together: // load related features
var related_features = FeatureSetByRelationshipName($feature, "RelationshipName")
// filter related features
var filtered_related_features = Filter(related_features, "Attribute = Value")
// create and fill the deletes array
var deletes = []
for(var f in filtered_related_features) {
Push(deletes, {"globalID": f.GlobalID})
}
// return
return {
"edit": [
{
"className": "RelatedFeatureClass",
"deletes": deletes
}
]
}
... View more
02-06-2022
10:10 PM
|
0
|
1
|
2331
|
|
POST
|
Open the "Fields view of your layer Select All, Copy (Ctrl + C) Open an Excel sheet, paste (Ctrl + V)
... View more
02-04-2022
01:27 AM
|
7
|
2
|
4076
|
|
POST
|
It absolutely has to do with screen size. From this page: Control when to turn on mobile layout The app supports two styles of layout based on the screen size. One is for desktop and one is for mobile devices. When either the height or width of a screen display is less than 600 pixels, the mobile layout applies automatically. However, this can result in unexpected behavior when the app is embedded in a website, for example, when the pop-up in the website is in the mobile layout style. To control the layout style, use mobileBreakPoint=<pixel number>. For example, you can remain in desktop style until the screen size is less than 300 pixels, as shown below: http://<your portal url>/apps/webappviewer/index.html?mobileBreakPoint=300
... View more
02-04-2022
01:21 AM
|
0
|
1
|
4143
|
|
POST
|
target_class = "path:/to/class_2"
append_class = "path:/to/class_1"
id_field = "RowID"
# read the ids that are already in the target class
existing_ids = [row[0] for row in arcpy.da.SearchCursor(target_class, [id_field])]
# create an SQL where clause "IdField NOT IN (1, 2, 3)"
if isinstance(existing_ids[0], str):
id_list = ["'{}'".format(i) for i in existing_ids]
else:
id_list = [str(i) for i in existing_ids]
where_clause = "{} NOT IN ({})".format(id_field, ", ".join(id_list))
# create a layer of all append features that are not in the target class, append
append_layer = arcpy.management.MakeFeatureLayer(append_class, "append_layer", where_clause)
arcpy.management.Append(append_layer, target_class)
... View more
02-04-2022
01:16 AM
|
2
|
10
|
5734
|
|
POST
|
These are the properties of the layer, not of the shapefile. A layer's properties are only stored in the map project or in a layer file. Nothing gets written to the underlying data. If you want to edit the shapefile's metadata, try using ArcCatalog: https://desktop.arcgis.com/en/arcmap/10.3/manage-data/metadata/viewing-metadata-from-arccatalog.htm
... View more
02-03-2022
02:48 AM
|
2
|
0
|
2713
|
|
POST
|
It works, but it appears to be calculating the centroid for the boundary geometry of the feature rather than the actual centroid of the linear feature (i.e. actually a point ON the line). Suggestions? Hmmm. I believe snapping the "false" centroid to the closest line segment would not yield the "correct" centroid, right? As for the beginning and ending vertices X,Y, I am at a loss // the geometry of line features has a "paths" attribute, which is a list of
// lists of points (multiple line segments)
// for polygons, the attribute is named "rings".
var first_point = Geometry($feature).paths[0][0]
var last_point = Geometry($feature).paths[-1][-1]
Is there a way to calculate a spatial relationship with Arcade? (Again, being new to this, this may be a no brainer). For instance, if I plot a point that is within the geometry of a polygon, I would like to do some equivalent of a spatial join to assign the point attribute(s) from the polygon. // load the polygons using one of the FeatureSetBy* functions
var fs_polygons = FeatureSetByName($datastore, "PolygonFC")
// find polygons intersecting the $feature
var intersecting_polygons = Intersects(fs_polygons, $feature)
// no polygons found -> return early
if(Count(intersecting_polygons) == 0) { return null }
// intersecting_polygons is a feature set, we want to access the attributes
// of polygon features, so we have to extract one of them.
// easiest, but not always appropriate, way is to just grab the first one.
var polygon = First(polygons)
// return some attribute
return polygon.Attribute
If you didn't know yet, the Arcade functions and classes are pretty well documented: Arcade functions: Function Reference | ArcGIS Arcade | ArcGIS Developer Arcade classes: Type System | ArcGIS Arcade | ArcGIS Developer
... View more
02-02-2022
11:31 PM
|
1
|
1
|
2352
|
|
POST
|
I don't know Geopandas, but if you have access to arcpy, you can do it like this: grid = "path:/to/grid.shp"
pipes = "path:/to/pipes.shp"
grid_id_field = "GridID" # unique identifier of your grid features
pipe_length_field = "PipeLength" # name of the new field
# intersect grid and pipes
intersection = arcpy.analysis.Intersect([grid, pipes], "memory/intersection")
# read intersection into a list
# [ (GridID, PipeShape) ]
intersection_list = [row for row in arcpy.da.SearchCursor(intersection, [grid_id_field, "SHAPE@"])]
# add the new field to the grid
arcpy.management.AddField(grid, pipe_length_field, "DOUBLE")
# loop through the grid and fill the new field
with arcpy.da.UpdateCursor(grid, [grid_id_field, pipe_length_field]) as cursor:
for grid_id, pipe_length in cursor:
# get all pipe shapes in this grid cell
pipe_shapes = [d[1] for d in intersection_list if d[0] == grid_id]
# get total length of those shapes
pipe_length = sum([s.length for s in pipe_shapes])
# update field values
cursor.updateRow([grid_id, pipe_length])
... View more
02-02-2022
07:19 AM
|
0
|
0
|
1654
|
|
POST
|
Something like this? // load the line fc
var lines = FeatureSetByName($datastore, "NameOfLineFC", ["GlobalID"], true)
// intersect with current line
var intersecting_lines = Intersects($feature, lines)
// we intersected $feature with itself, so we need to filter it out
var f_gid = $feature.GlobalID
intersecting_lines = Filter(intersecting_lines, "GlobalID <> @f_gid")
// loop through all intersecting lines
// return the GlobalID of the first line where the end point is the same as $feature's end point
var feature_end = Geometry($feature).paths[0][-1]
for(var line in intersecting_lines) {
var line_end = Geometry(line).paths[0][-1]
if(Intersects(feature_end, line_end)) {
return line.GlobalID
}
}
// if we land here, there is no line with intersecting end point
return null
... View more
02-01-2022
02:09 AM
|
2
|
3
|
1822
|
|
POST
|
What format do the photos in the attachment table need to be? The field mapping only recognizes BLOB (Binary Large OBject, so byte data) fields. If you have an ArcGIS Attachment table, there should be a BLOB field in there. If not, you can also create a BLOB field in your feature class and store the images there. And do you think there would be a way to dynamically offset all the labels so that the points don't get obscured (maybe in Python)? Dynamically? Probably not, for that you need to work with labels, not symbology. Maaaaaybe with Point Clustering in 2.9, but it doesn't seem likely. With Python? You could map X and Y offset to fields in your feature class. You could then calculate these fields with Python, using the distance to nearby points as input. This could work for a fixed map scale and picture marker size. But as soon as you zoom out, the images will overlap each other again. A simple approach to that with Arcade: // calculate field OffsetX
// load other features
var gid = $feature.GlobalID
var fs = Filter(FeatureSetByName($datastore, "FeatureClass"), "GlobalID <> @gid")
// get nearby features
var nearby_features = Intersects(fs, Buffer($feature, 50))
// gravitational force in horizontal direction
var force = 0
for(var f in nearby_features) {
var dist = Distance($feature, f)
var dx = Geometry(f).X - Geometry($feature).X
force -= dx / (dist * dist)
}
// magical number dependent on map scale and picture marker size
var magic_factor = 100
return force * magic_factor // calculate field OffsetY
// load other features
var gid = $feature.GlobalID
var fs = Filter(FeatureSetByName($datastore, "FeatureClass"), "GlobalID <> @gid")
// get nearby features
var nearby_features = Intersects(fs, Buffer($feature, 50))
// gravitational force in vertical direction
var force = 0
for(var f in nearby_features) {
var dist = Distance($feature, f)
var dy = Geometry(f).Y - Geometry($feature).Y
force -= dy / (dist * dist)
}
// magical number dependent on map scale and picture marker size
var magic_factor = 100
return force * magic_factor Without offsets: With offsets: But it only works for a fix scale. When you zoom out, the images overlap again:
... View more
01-27-2022
04:30 AM
|
1
|
0
|
10757
|
|
POST
|
A working, but basic approach: Join the Attachment table to the feature class. You can now choose the DATA field of the attachment table as input for the picture marker Basically, that's it. To make it prettier: Set size and quality, set position to "Center bottom" Add a marker layer on top of the picture layer, style it rotate the whole symbol using a rotation field Before: After: I'm sure you could hack together a border around the picture somehow. Unlike labels, symbols don't seem to have options for dynamic placement. Position and offset are either taken as values provided by the user or by a table field. I haven't found a way to use labels for this task. You can't use the Attachments() and FeatureSetBy*() function in the Arcade label expression, and the DATA field of the joined attachment table is also not available. I thought I had something using a Python label expression and trying to return an HTML <img> tag with a data uri, but it doesn't seem to work (it's because there are only a few text formatting tags allowed; I'll still leave the code here, maybe it helps): def FindLabel([GlobalID]):
import arcpy
import base64
att_table = 'path:/to/database.sde/Fotos__ATTACH'
sql = "REL_GLOBALID = '{}'".format([GlobalID])
cur = arcpy.da.SearchCursor(att_table, ['CONTENT_TYPE', 'DATA'], sql)
for row in cur:
b64 = base64.encodebytes(row[1])
data_uri = 'data:{};base64,{}'.format(row[0], b64)
#return data_uri[:30] # this returns the start of the data_uri correctly
return '<img src="{}"/>'.format(data_uri) # this returns without error, but doesn't do anything
return "N/A" Don't know anything about JScript, maybe you can do something with that.
... View more
01-26-2022
08:20 AM
|
3
|
6
|
10786
|
|
POST
|
Actually, if you use this expression, you can use it for all geometry types: // base url of your Dashboard
// if there's no "?" in the URL, add one at the end, else add "&"
var url = "https://company.maps.arcgis.com/apps/dashboards/123?"
//var url = "https://company.maps.arcgis.com/apps/dashboards/index.html?id=123&"
// how much do you want to zoom out?
var buffer_dist = 200
// use the extent parameter
var ext = Extent(Buffer($feature, buffer_dist))
var ext_par = "extent=" + Concatenate([ext.xMin, ext.yMin, ext.xMax, ext.yMax, ext.spatialReference.wkid], ",")
return url + ext_par
... View more
01-24-2022
01:44 AM
|
0
|
1
|
2450
|
|
POST
|
Documentation for using URL parameters can be found here: Use URL parameters to create and modify maps—ArcGIS Online Help | Documentation I don't have a Dashboard to test, but it works for a WebApp. // base url of your Dashboard
// if there's no "?" in the URL, add one at the end, else add "&"
var url = "https://company.maps.arcgis.com/apps/dashboards/123?"
//var url = "https://company.maps.arcgis.com/apps/dashboards/index.html?id=123&"
// get the geometry of your feature
// I'm working with point features, if you have lines/polygons, call Centroid
var geo = Geometry($feature) // var geo = Centroid($feature)
// option 1: use center and level parameters
// center is formatted as "x,y,wkid"
var level = "level=15"
var center = "¢er=" + Concatenate([geo.x, geo.y, geo.spatialReference.wkid], ",")
return url + level + center
// option 2: use extent parameter
// extent is formatted as "min_x,min_y,max_x,max_y,wkid"
var ext_width = 200
var ext_height =200
var ext = "extent=" + Concatenate([geo.x-ext_width/2, geo.y-ext_height/2, geo.x+ext_width/2, geo.y+ext_height/2, geo.spatialReference.wkid], ",")
return url + ext
... View more
01-23-2022
10:45 PM
|
0
|
2
|
2452
|
|
POST
|
When there are no related features, you call First() on an empty feature set, which will return null. You just have to check the size of the feature set before calling First() on it: var relationship = FeatureSetByRelationshipName($feature, 'Device_Hydrant_To_Inspection', ['hast_assetid'], false);
// check size of FeatureSet, return null if empty
if(Count(relationship) == 0) { return null }
return First(relationship).hast_assetid
... View more
01-23-2022
10:04 PM
|
1
|
3
|
7948
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 01-30-2023 09:57 AM | |
| 1 | 05-18-2023 12:51 AM | |
| 1 | 03-05-2023 12:46 PM | |
| 1 | 12-07-2022 07:01 AM | |
| 1 | 06-21-2022 08:27 AM |
| Online Status |
Offline
|
| Date Last Visited |
02-03-2024
06:14 PM
|