|
POST
|
There is Union(). With that, you can union/dissolve multiple geometries.
... View more
12-11-2022
11:27 PM
|
0
|
2
|
3005
|
|
POST
|
I'm trying to get GroupBy() to calculate the total length of features in the group. In MS SQL, I can get it like this: SELECT
MAX(OBJECTID) AS "OID",
COUNT(1) AS "PartCount",
SUM(Shape.STLength()) AS "TotalLength"
FROM mytable
GROUP BY myfield If I try to do this in Arcade, it fails (complains about the parantheses): //var fs = FeaturesetByPortalItem(...)
return GroupBy(fs, ["myfield"], [
{name: "PartCount", expression: "1", statistic: "COUNT"},
{name: "TotalLength", expression: "Shape.STLength()", statistic: "SUM"},
]) If I try to sum Shape__Length, it returns an empty Featureset. If I do the sum over the whole fs it works, I guess it just takes too long with the filtering. Is there a way to get a sum of the shape lengths in each group without doing it manually (and without having a dedicated field in the fs)?
... View more
12-11-2022
11:26 PM
|
1
|
0
|
899
|
|
IDEA
|
The question is a bit unclear. Yes, there is symbol.angle, but that sets the angle value of each symbol. What @Bud means is that there is no way in arcpy to Vary symbology by rotation—ArcGIS Pro | Documentation
... View more
12-11-2022
11:20 PM
|
0
|
0
|
3468
|
|
IDEA
|
I think you're missing something. The query has 4 states: active, normal active, hover inactive, normal inactive, hover The grey checkmark in the inactive hover state is meant to tell you "Hey, click here to activate this query!" You have something different going on there: The query shows as inactive, although it apparently is active. Could be that this is due to your more complex query. Try a simple one.
... View more
12-11-2022
11:03 PM
|
0
|
0
|
2430
|
|
POST
|
Oh, that's just unfortunate naming of the variable. Despite me calling the variable query_layer, I'm not using Make Query Layer (which, correct, can only be used with an Enterprise gdb). Instead, I'm using Make Feature Layer, which takes an optional where clause and can be used with all feature sources (fgdb, egdb, feature service, shape file, ...). It basically creates a new layer and sets its definition query.
... View more
12-09-2022
08:29 AM
|
1
|
0
|
1833
|
|
POST
|
If you're using a raster based approach, it's probably enough to create a cost raster where land has a very high cost. If you have a polygon feature class representing land, you can also use this script: land_fc = "Land"
source_fc = "Source"
station_fc = "Stations"
distance_to_coast = 50 # to separate the paths from the land polygons
# can be 0
# should be less than the distance of the stations to land
output_folder = "memory"
output_name = "ShortestPath"
def get_shortest_line(start_point, end_point, barrier_polygons, max_iter=50):
iter_count = 0
do_it_again = True
line = arcpy.Polyline(arcpy.Array([start_point.firstPoint, end_point.firstPoint]))
while do_it_again and iter_count < max_iter:
# loop over the line segments
line_segments = [arcpy.Polyline(arcpy.Array([line[0][i-1], line[0][i]])) for i in range(1, len(line[0]))]
for i, segment in enumerate(line_segments):
# create the array to store the updated segment's vertices
new_vertices = [segment.firstPoint]
# loop over the barriers
for barrier_polygon in barrier_polygons:
# cut barrier polygon with segment
try:
barrier_split = barrier_polygon.cut(segment)
except:
continue
# get the smallest half and its vertex that is furthest from the line
# -> shortest way around the barrier
try:
small_split = sorted(barrier_split, key=lambda s: s.area)[0]
vertices = [arcpy.PointGeometry(v) for v in small_split[0]]
furthest_vertex = sorted(vertices, key=lambda v: v.distanceTo(segment))[-1]
except:
continue
new_vertices.append(furthest_vertex.firstPoint)
# update the segment
new_vertices.append(segment.lastPoint)
line_segments[i] = arcpy.Polyline(arcpy.Array(new_vertices))
# update the line
old_line = line
line = line_segments[0]
for segment in line_segments:
line = line.union(segment)
# if the line didn't change, we're finished
do_it_again = not line.equals(old_line)
iter_count += 1
return line
# dissolve and buffer the land fc
arcpy.env.addOutputsToMap = False
land_dissolve = arcpy.management.Dissolve(land_fc, "memory/LandDissolve", multi_part=False)
if distance_to_coast:
land_dissolve = arcpy.analysis.Buffer(land_dissolve, "memory/Coastline", distance_to_coast)
arcpy.env.addOutputsToMap = True
# extract the land polygons and the source point
land_polygons = [row[0] for row in arcpy.da.SearchCursor(land_dissolve, ["SHAPE@"])]
source = [row[0] for row in arcpy.da.SearchCursor(source_fc, ["SHAPE@"])][0]
# create the output fc
out_fc = arcpy.management.CreateFeatureclass(output_folder, output_name, "POLYLINE")
arcpy.management.AddField(out_fc, "FID", "LONG")
arcpy.management.AddField(out_fc, "Length", "DOUBLE")
# calculate the shortest path for each station
with arcpy.da.InsertCursor(out_fc, ["SHAPE@", "FID", "LENGTH"]) as i_cursor:
with arcpy.da.SearchCursor(station_fc, ["OID@", "SHAPE@"]) as s_cursor:
for oid, station in s_cursor:
shp = get_shortest_line(source, station, land_polygons)
i_cursor.insertRow([shp, oid, shp.length]) This will create a Polyline fc with the shortest paths between the source and the stations. You can join it to the stations via Station.OBJECTID = ShortestPath.FID The tuqouise polygons represent land around a semi-fictional bay, the red dot is the source.
... View more
12-09-2022
08:17 AM
|
1
|
0
|
934
|
|
POST
|
As @Alaind_Espaignet said, that's a very common use case for Attribute Rules. A very basic Attribute rule for transferring a single value ( @Alaind_Espaignet scenario): // Calculation Attribute Rule on the point fc
// field: the field you want to fill
// triggers: Insert(, Update)
// load the other featureset
var fs = FeaturesetByName($datastore, "NameOfTheFC")
// get the first feature from fs that intersects the current $feature
var f = First(Intersects(fs, $feature))
// abort if we didn't find something
if(f == null) { return }
// return the intersecting feature's value
return f.Field And for multiple fields ( @AndrewReynoldsDevon scenario): // Calculation Attribute rule on the point fc
// field: empty!
// triggers: Insert(, Update)
// load the other featuresets
var fs1 = FeaturesetByName($datastore, "NameOfTheFirstFC")
var fs2 = FeaturesetByName($datastore, "NameOfTheSecondFC")
// get the first feature from fs1 that intersects the current $feature
var f1 = First(Intersects(fs1, $feature))
// if there is no intersecting feature, use a default value, else use that feature's field value
var value1 = Iif(f1 == null, null, f1.Field)
// do the same for fs2
var f2 = First(Intersects(fs2, $feature))
var value2 = Iif(f2 == null, null, f2.Field)
// return
return {
result: {attributes: {
Field1: value1,
Field2: value2
}}
}
... View more
12-09-2022
03:09 AM
|
0
|
0
|
3389
|
|
POST
|
No idea about the SDK, but you can convert the layer to multiple query layers: def convert_unique_symbol_layer_to_query_layers(layer_name):
# get the symbology fields and items
layer = arcpy.mp.ArcGISProject("current").activeMap.listLayers(layer_name)[0]
renderer = layer.symbology.renderer
fields = renderer.fields
items = renderer.groups[0].items
# loop over the items
for item in reversed(items):
# create the query layer
values = item.values[0]
query = " AND ".join([f"{fields[i]} = '{values[i]}'" for i in range(len(fields))])
print(f"Creating query layer {item.label} with query {query}")
query_layer = arcpy.management.MakeFeatureLayer(layer, item.label, query)[0]
# change the symbology
symbology = query_layer.symbology
symbology.updateRenderer("SimpleRenderer")
symbology.renderer.symbol = item.symbol
query_layer.symbology = symbology
convert_unique_symbol_layer_to_query_layers("Bauwerke") I haven't found a way to apply symbol rotation with arcpy, so that's a smallish problem for point layers (eg the "Brücke" layer).
... View more
12-09-2022
02:54 AM
|
1
|
0
|
1842
|
|
POST
|
It doesn't allow you to select singlepart features. You should be able to select actual multipart features. I can't select polygon 1, because it has only one part. I can select polygon 2 just fine.
... View more
12-08-2022
04:25 AM
|
2
|
0
|
2167
|
|
POST
|
Alternatively, you can also take the script I posted in @Bud 's question and replace the junk_values list: def check_for_junk_values(layer_or_table):
fields = [f.name for f in arcpy.ListFields(layer_or_table)]
junk_values = [None]
data = [dict(zip(fields, row)) for row in arcpy.da.SearchCursor(layer_or_table, fields)] # [{"Field1": 0, "Field2": 1}, {"Field1": 5, "Field2": 2}]
counts = dict()
for row in data:
for field, value in row.items():
if value in junk_values:
key = (field, value)
try:
counts[key] += 1
except KeyError:
counts[key] = 1
return counts
tables = ["TestPoints", "TestLines", "TestPolygons", "TestTable"]
# you can also use paths to your tables, or list them automatically with arcpy.ListTables() / arcpy.ListFeatureclasses()
log_table = arcpy.management.CreateTable("memory", "JunkLogTable")
arcpy.management.AddField(log_table, "TABLE_NAME", "TEXT")
arcpy.management.AddField(log_table, "COLUMN_NAME", "TEXT")
arcpy.management.AddField(log_table, "VAL_COUNT", "SHORT")
arcpy.management.AddField(log_table, "VALUE", "TEXT")
with arcpy.da.InsertCursor(log_table, ["TABLE_NAME", "COLUMN_NAME", "VALUE", "VAL_COUNT"]) as cursor:
for table in tables:
result = check_for_junk_values(table)
for key, count in result.items():
col = key[0]
val = key[1].__repr__() # __repr__() to get the quotes
cursor.insertRow([table, col, val, count]) This results in a log table which lists the found fields more precisely:
... View more
12-08-2022
01:17 AM
|
2
|
0
|
3457
|
|
POST
|
def check_for_junk_values(layer_or_table):
fields = [f.name for f in arcpy.ListFields(layer_or_table)]
junk_values = [0, " ", " ", "-", "0", "NULL", "<NULL>", "<Null>"]
data = [dict(zip(fields, row)) for row in arcpy.da.SearchCursor(layer_or_table, fields)] # [{"Field1": 0, "Field2": 1}, {"Field1": 5, "Field2": 2}]
counts = dict()
for row in data:
for field, value in row.items():
if value in junk_values:
key = (field, value)
try:
counts[key] += 1
except KeyError:
counts[key] = 1
return counts
tables = ["TestPoints", "TestLines", "TestPolygons", "TestTable"]
# you can also use paths to your tables, or list them automatically with arcpy.ListTables() / arcpy.ListFeatureclasses()
log_table = arcpy.management.CreateTable("memory", "JunkLogTable")
arcpy.management.AddField(log_table, "TABLE_NAME", "TEXT")
arcpy.management.AddField(log_table, "COLUMN_NAME", "TEXT")
arcpy.management.AddField(log_table, "VAL_COUNT", "SHORT")
arcpy.management.AddField(log_table, "VALUE", "TEXT")
with arcpy.da.InsertCursor(log_table, ["TABLE_NAME", "COLUMN_NAME", "VALUE", "VAL_COUNT"]) as cursor:
for table in tables:
result = check_for_junk_values(table)
for key, count in result.items():
col = key[0]
val = key[1].__repr__() # __repr__() to get the quotes
cursor.insertRow([table, col, val, count])
... View more
12-08-2022
12:36 AM
|
1
|
0
|
2741
|
|
POST
|
It should be completely independent from the dbms and version, as arcpy handles all the interfacing with the database. Working on your question right now.
... View more
12-08-2022
12:09 AM
|
0
|
0
|
3472
|
|
POST
|
MapSeries.exportToPdf() activates each page of the series and exports them into the same pdf. You do that process for each page. What you want to do is activate each page, then export the layout. aprx = arcpy.mp.ArcGISProject(ProProject)
try:
msLayout = aprx.listLayouts('Neighborhoods MapBook')[0] ## the number in brackets is the number in the layout
print ('Layout {}'.format(msLayout.name))
if not msLayout.mapSeries is None:
ms = msLayout.mapSeries
ms.refresh()
if ms.enabled:
for pageNum in range(1, ms.pageCount + 1):
ms.currentPageNumber = pageNum
pageName = ms.pageRow.NHNAME
msLayout.exportToPDF(os.path.join(OutFolder, f"NeighborhoodsMapBook_{ms.pageRow.NHNAME}.pdf"))
print(ms.pageRow.NHNAME + ' exported')
except:
message = arcpy.GetMessages()
... View more
12-08-2022
12:02 AM
|
1
|
1
|
2686
|
|
POST
|
Just start up a SearchCursor for each layer / table: def check_for_null_values(layer_or_table):
fields = [f.name for f in arcpy.ListFields(layer_or_table)]
sql = " OR ".join([f"{field} IS NULL" for field in fields])
num_rows = 0
empty_fields = []
with arcpy.da.SearchCursor(layer_or_table, fields, sql) as cursor:
for row in cursor:
num_rows += 1
for i, value in enumerate(row):
if value is None:
empty_fields.append(fields[i])
empty_fields = sorted(set(empty_fields))
return (num_rows, empty_fields)
layers = ["TestPoints", "TestLines", "TestPolygons", "TestTable"]
for layer in layers:
result = check_for_null_values(layer)
print(f"{layer} contains {result[0]} rows with null values. Fields: {', '.join(result[1])}") TestPoints contains 3 rows with null values. Fields: DISTANCE, DateField, DateField2, #...
TestLines contains 0 rows with null values. Fields:
TestPolygons contains 1 rows with null values. Fields: IntegerField
TestTable contains 71 rows with null values. Fields: DateField, DateField2, #...
... View more
12-07-2022
11:41 PM
|
1
|
0
|
3488
|
| 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
|